使用 new 关键字和不使用它的指针初始化

Pointer initialization with new keyword and without it

当我尝试以另一种方式声明指针时,我尝试使用 new 关键字并尝试一下:

#include<iostream>
using std::cin;
using std::cout;
using std::endl;

int main ()
{
    int *p = new int;
    *p = 5;
    cout << *p << endl;

    return 0;
}

但是当我尝试声明相同的指针但没有 new 关键字时,它给我一个错误,如下面的代码:

#include<iostream>
using std::cin;
using std::cout;
using std::endl;

int main ()
{
    int *p;
    *p = 5;
    cout << *p << endl;

    return 0;
}

那么这个错误的原因是什么,这两种方式有什么区别?

new int在堆上占用一块新内存space,p指向那块内存space。但是在第二个例子中,你没有指定 p 指向哪里(所以 p 可以指向任何地方,但是你尝试分配内存地址 p 点,所以它导致 undefined行为。

你应该知道其中的区别。

int *p;

这里,p只是栈上的一个变量。它还没有被初始化,所以它不指向内存中的特定位置。因此,当您取消引用它并为基础位置分配一个值时,您正在调用一些未定义的行为。换句话说,您还没有在堆上分配任何 space 来存储 int。所以在这里:

*p = 5;

您可能将值 5 分配给了不属于您的程序的位置。

现在在这里:

int *p = new int;
*p = 5;

这很好。 new 运算符将在堆内存上保留 4 个字节,return 它的地址,该地址存储在 p 中,现在 p 包含一个实际和合法的地址能够存储 int 的内存块。因此取消引用 p 并为基础位置赋值是安全的。

重要说明:您几乎不应该处理 new/deletenew[]/delete[] 运算符和原始指针。相反,您应该尽可能使用 smart pointers and stick to RAII
因此,正确的做法应该是这样的:

#include<iostream>
#include<memory>

using std::cin;
using std::cout;
using std::endl;

int main ()
{
    std::unique_ptr<int> p { std::make_unique<int>( 5 ) };
    cout << *p << endl;

    return 0;
}

但是,在这种情况下使用任何类型的指针都是浪费,因为您还可以在堆栈上存储小类型:

int num { 5 };

这是存储值的首选方式,除非您迫切希望使用动态内存分配(出于某种原因,例如您可能希望对象具有动态存储持续时间,或者对象可能很大且不适合在堆栈上)。