我正在学习 C++,我开始知道如果未初始化的指针可能指向内存中的随机位置,并产生内存可能被其他程序使用的问题。
现在,如果是这种情况,我们不应该在代码的任何部分中包含这一行:
int* ptr;
相反,我们应该有类似的东西
int* ptr = NULL; //Is this going to avoid the problem
请提出建议,因为我在很多书中都看到了第一行(int* ptr;
),所以我有这个疑问。如果可能的话,也举一些例子。
我正在学习 C++,我开始知道如果未初始化的指针可能指向内存中的随机位置,并产生内存可能被其他程序使用的问题。
现在,如果是这种情况,我们不应该在代码的任何部分中包含这一行:
int* ptr;
相反,我们应该有类似的东西
int* ptr = NULL; //Is this going to avoid the problem
请提出建议,因为我在很多书中都看到了第一行(int* ptr;
),所以我有这个疑问。如果可能的话,也举一些例子。
int* ptr = NULL; //Is this going to avoid the problem
这将导致ptr
指向NULL
您可以显式检查的默认/未初始化值。它可以防止您描述的问题,但是粗心的程序员仍然可以在不检查的情况下意外取消引用空指针,从而导致未定义的行为。
主要优点是您可以方便地检查 是否ptr
已初始化为任何内容,即:
if (ptr != NULL)
{
// assume it points to something
}
由于这是非常惯用的,因此不将指针初始化为NULL
. 指针将被初始化为一个非 NULL 垃圾值,它并不真正指向任何真实的东西。最糟糕的是,上面的检查会通过,如果恰好指针中的地址是您可以合法访问的内存,则会导致更严重的问题。在某些嵌入式环境中,您可能能够访问内存的任何部分,因此您可能会意外损坏内存的随机部分或执行代码的随机部分。
始终初始化您的变量。
有时,您可能希望初始化为NULL
,但大多数时候,您应该能够将指针初始化为它应该持有的值。尽可能晚地声明变量,并在此时初始化它们,而不是代码中的 15 行。
该行:
int* ptr;
绝对不能保证将指针值初始化为任何特定的值。该行:
int* ptr = NULL;
将初始化指针以指向地址零,实际上它永远不会保存任何有用的东西,并且通常会检查它是否为无效指针值。
当然,正如 Doug T. 所说,仍然有可能尝试使用该指针而不检查它,因此它仍然会崩溃。
显式初始化为 NULL 的优点是确保在将指针设置为有用的值之前取消引用指针会崩溃,这实际上是一件好事,因为它可以防止代码在掩盖严重错误的同时“意外”工作。
如果由于任何原因在声明发生时无法对其进行初始化,则最好将指针初始化为 NULL。例如:
Object *ptr = new Object();
通常,函数可以根据 NULL 检查指针的值,以验证指针之前是否已初始化。如果您没有将它显式设置为 NULL,并且它指向一个随机值,那么它可能会被取消引用,从而导致段错误。
C++ 继承于 C,因为它不是为了安全而设计的。它旨在提高效率。因此,自动变量没有被初始化。您可以确保在初始化之前不使用任何指针(尽管如果您不初始化变量,许多编译器会警告您)
如果不使用指针,编译器将简单地忽略它。恕我直言,将其初始化为 NULL 是安全的做法。
你确定你不会对函数声明感到困惑吗?一个函数被声明为是很常见的
char* do_something(const char* 一,const char* 二);
在这种情况下,指针用于指定要传递的参数类型。
int a,*ptr;
现在
print(ptr,*ptr)
在上面的代码中可能有两种情况:
如果 ptr 中的默认值不是程序的某些已用内存的地址,它将执行。
输出:
ptr *ptr
eg. 0x400730 -1992206795
如果 ptr 中的默认地址是程序的某些已用内存的地址,它将给出错误(段错误)。例如,如果变量 a 在内存中的地址也是 0x400730。
在 C++ 中,您通常应该完全避免使用普通的旧指针。标准库类、智能指针(直到 C++0x 仅在 Boost 或 Loki 等各种库中)和引用可以而且应该在大多数地方使用。
如果你不能避免指针,确实最好用初始化来声明它们,在大多数情况下它不应该是 NULL,而是实际的目标值,因为在 C++ 中你可以自由地混合声明和表达式,所以你可以而且应该只声明变量在你有有意义的价值点。
在 C 语言中,您必须大量使用指针,并且所有变量都必须(或必须在 C99 之前;我不确定)在作用域的开头声明,情况并非如此。很多人仍然有不适合 C++ 的 C 的坏习惯。