试图理解C++中的指针

Trying to understand pointers in C++

本文关键字:指针 C++      更新时间:2023-10-16

我正在尝试使用Jesse Liberty的"在24小时内自学C++"自学C++。我写了这个简短的程序来找出C++中的指针。

#include <iostream>
void hMany(int count); // hMany function prototype

void hMany(int count){
    
    do {
        std::cout << "Hello...n";
        count--;
        
        }  while (count >0 );
        
};

int main (int argc, const char * argv[]) {
    
    int counter;
    int * pCounter = &counter;
    
    std::cout << "How many hellos? ";
    std::cin >> counter;
    
    hMany(*pCounter);
    
    std::cout << "counter is: " << counter << std::endl;
    std::cout << "*pCounter is: " << *pCounter << std::endl;
    
    return 0;
}

生成的输出为:

How many hellos? 2
Hello...
Hello...
counter is: 2
*pCounter is: 2

传递指针(*pCounter(与参数(计数器(有什么好处?

任何帮助将不胜感激。路易斯

更新:

还行。该程序正在运行,我现在完全理解C++指针。 谢谢大家的回复。尝试 Chowlett 的代码后,我收到了 2 个警告(不是错误(。一个是 !没有函数hMany和*pCount的先前原型-- !表达式结果未使用。我能够自己纠正原型,但我无法弄清楚*pCount-警告。

向我的朋友托尼寻求帮助,这是他的答案。

括号使事情以正确的顺序发生。

(*pCount)--

说跟随指针指向它指向的整数,然后递减整数,这就是你想要做的。

*pCount--

最终做错了事,编译器将其视为

*(pCount—)

它说首先递减指针,让它指向您要更改的指针之前的"整数"(没有这样的事情,因为您只有一个整数调用此函数(,然后遵循这个递减指针并且不对该内存位置的整数执行任何操作。 这就是编译器抱怨表达式结果未使用的原因。 编译器是正确的。 此代码错误地递减指针,提取错误的整数,并且不会在任何地方存储该错误的整数。

这是那些可能感兴趣的新C++的正确代码。

包括

void hMany(int *pCount(;//hMany function prototype

void hMany(int *pCount({//*pCount 接收 count 的地址

do {
    std::cout << "Hello...n";
   
    
    // The parentheses make things happen in the correct order.
    // says to follow the pointer to the integer it points to, 
    // and then decrement the integer.
    
          (*pCount)--; 
    
}  while (*pCount >0 );

}

int main (int argc, const char * argv[]( {

int counter;
int * pCounter = &counter;
std::cout << "How many hellos? ";
std::cin >> counter;
hMany(pCounter); // passing the address of counter
std::cout << "counter is: " << counter << std::endl;
std::cout << "*pCounter is: " << *pCounter << std::endl;
return 0;

}

int counter;
int * pCounter = &counter;
...
hMany(*pCounter); // Pass by value
hMany(counter);   // Pass by value

传递点(*pCounter(与参数有什么好处 (柜台(?

在这种情况下,什么都没有,这只是一个教育示例。它显示您可以取消引用指针并通过*获取其值。

此外,这两种情况都是按值传递的。

实际上,除非

有充分的理由,否则默认情况下应避免使用指针。

使用 *pCountercounter 没有区别。在这两种情况下,您都将传递变量的值counter 。但是,如果您实际传递指针本身,则会得到不同的行为。

考虑稍微不同的程序:

#include <iostream>
void hMany(int* pCount); // hMany function prototype

void hMany(int* pCount){
    do {
        std::cout << "Hello...n";
        --*pCount;
        }  while (*pCount >0 );
}

int main (int argc, const char * argv[]) {

    int counter;
    int * pCounter = &counter;
    std::cout << "How many hellos? ";
    std::cin >> counter;
    hMany(pCounter);
    std::cout << "counter is: " << counter << std::endl;
    std::cout << "*pCounter is: " << *pCounter << std::endl;
    return 0;
}

在这种情况下,您的输出将是:

How many hellos? 2
Hello...
Hello...
counter is: 0
*pCounter is: 0

通过传入指向counter指针(字面意思是内存中的地址 counter (,您可以允许函数通过其内存位置更改counter

传递点(*pCounter(与参数有什么好处 (柜台(?

没有"好处">,这就是你应该如何传递指针指向的值pCounter

hMany(*pCounter) ->取消引用pCounter以获取值

区别在于变量的作用域。

如果传递变量,则会将其复制到函数本地范围内的堆栈中。更改值比在调用函数的本地副本中完成,如果是这种情况,如果是这种情况,则传递大变量,则首先使用空间,其次您需要从函数返回值(因为堆栈将在返回后被销毁(

你可以这样想:

叠:

当前函数栈:

[    ]
[    ]
[    ]
[    ]

当您调用另一个 1 个元素时,添加了另一个元素

[    ]
[    ]
[    ]
[    ]
[newel]

当您离开该功能时,它会被删除,因此再次像这样

[    ]
[    ]
[    ]
[    ]

新元素值不能再被信任了。

但是,如果这是指针的副本,则不会更改指针复制值但是它所指向的地方的价值也是如此,所以堆栈将是这样的

[    ]
[ actual_value]
[    ]
[ pointer_to_value]

比你调用函数

[    ]
[ actual_value]
[    ]
[ pointer_to_value]
[ pointer_to_value_copy]

这将更改堆栈上的actual_value并退出删除pointer_to_value的副本

[    ]
[ actual_value**changed]
[    ]
[ pointer_to_value]

指针实际上包含内存地址以及内存地址所表示的值的类型信息。它可用于传递内存地址中的实体,而无需再次实例化它以更改其值或类似的东西。

但是在您的程序中,我看不到使用指针的任何好处,因为C++函数(hMany在您的情况下(在其参数中内部重新实例化值的类型,在您的情况下为"int count"。

正如其他答案所指出的,您需要将计数指针传递给函数。在这种情况下,C++函数将类似地重新实例化其参数中的值类型,但由于类型是指针,因此程序将在C++函数内部具有正确的内存地址count,并且可以正确更改正确标识的值。