使用 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
/delete
或 new[]
/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 };
这是存储值的首选方式,除非您迫切希望使用动态内存分配(出于某种原因,例如您可能希望对象具有动态存储持续时间,或者对象可能很大且不适合在堆栈上)。
当我尝试以另一种方式声明指针时,我尝试使用 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
/delete
或 new[]
/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 };
这是存储值的首选方式,除非您迫切希望使用动态内存分配(出于某种原因,例如您可能希望对象具有动态存储持续时间,或者对象可能很大且不适合在堆栈上)。