我正在学习C ++,我对指针有疑问。
我有这段代码:
int* max = new int;
*max = 0;
我想,我在堆上创建了一个指针(如果我不对,请告诉我)。
一个问题:
有没有办法用一条指令创建一个初始化指针?(现在,我用两条指令)。
另一个问题:
如何在堆栈上创建指针?
我看到这样的代码:
int myVar = 20;
int* pVar = &myVar;
我认为我还没有在堆栈上创建指针,但我认为这是不在堆上创建指针的唯一方法。
我在C ++开发方面非常非常新。
答案 0 :(得分:9)
指针是正常变量,其内容是内存地址。该内存可以是堆内存或堆栈内存。不要将指针与它指向的内存空间混淆。
你的第一个代码在堆上分配空间,它可以容纳一个int。您将指向存储器的指针存储在堆栈。
你的第二个代码在堆栈上分配空间,它可以容纳一个int。您将指向存储器的指针存储在堆栈。
所以两个指针都在堆栈上,但只有第二个指向堆栈。
在这两种情况下,您分配的类型都是基本类型。默认情况下,初始类型不会初始化,除非您立即为其分配值(第二个代码),或使用构造函数语法,这也适用于堆分配的值:
int *max = new int(0);
顺便说一下,在第二个代码中可以使用相同的语法:
int myVar(20);
如果您感兴趣:您还可以在堆上定义指针。 int*
是指向int
的指针类型,所以请继续在堆上分配这样的类型:
new int*();
此表达式返回int**
,然后您可以将其存储在某处。同样,您通常将此指针存储在堆栈中:
int **pointerToPointer = new int*();
与int
一样,您可以将new-expression中的int*
初始化为某个指向int的指针(此处为上面的max
指针):
int **pointerToPointer = new int*(max);
现在你有两个指针具有相同的地址:max
(堆栈上的指针)和堆上的一些指针,你指向使用pointerToPointer
,即跟随保持(我取消引用`pointerToPointer,它导致存储在该指针后面的值,这是一个指向int的指针):
max == *pointerToPointer
答案 1 :(得分:7)
int* max = new int;
上面的行在堆栈上创建一个指针,并使用存储在堆上的整数对其进行初始化。每当new
涉及表达式时,它将返回指向其动态创建的操作数的指针:
根据C ++ 11标准的第5.3.4 / 2段:
由
new
- 表达式创建的实体具有动态存储持续时间(3.7.4)。 [ - ] 如果实体是非数组对象,则new-expression返回指向所创建对象的指针。如果它是一个数组,new
- 表达式返回一个指向数组初始元素的指针。
int myVar = 20;
int* pVar = &myVar;
在此示例中,指针及其值都存储在堆栈中。 new
- 表达式没有参与赋值,因此在这种情况下堆上没有创建任何内容。
如果要在一行中初始化指向对象的值,则必须 value-initialize ,如下所示:
int* max = new int(5);
或在C ++ 11中,您可以使用统一初始化:
int* max = new int{5};
记住使用delete
创建的new
也很重要。由于内存处于动态分配状态,因此其生命周期不依赖于其创建范围。如果您忘记delete
您的程序将导致内存泄漏。
delete max;
如果max
是指向由new
- 表达式创建的数组的指针,则使用delete[]
:
delete[] max;
注意:如果指针不由new
- 表达式初始化,则无需删除。
通常建议您使用容器为您管理内存。像std::unique_ptr
这样的东西会做。一旦调用了析构函数,就会删除它所拥有的内存:
std::unique_ptr<int> max{new int{5}};
在C ++ 14中,我们有make_unique
:
auto max = std::make_unique<int>(5);
答案 2 :(得分:2)
有没有办法用一条指令创建一个初始化指针?
是:
int * a = new int(20); //initialized with 20;
如何在堆栈上创建指针?
int myVar = 20;
int* pVar = &myVar; //copied your code snipped It's alright
答案 3 :(得分:1)
你的第一个例子
int* max = new int;
*max = 0;
确实在堆上创建了一个新的int,而你的变量max
保存了一个指向该int的指针。如果您打算使用它,那么当您不再需要它时,您将不得不使用delete max;
来避免内存泄漏。
第二个例子
int myVar = 20;
int* pVar = &myVar;
在堆栈上创建一个int,pVar
现在是一个指向int保存在内存中的地址的指针。但是,如果您使用此功能,则不必删除pVar
,因为它不在堆上(您没有使用new
关键字)。
两个变量(在堆和堆栈上创建)之间的主要区别在于堆栈变量在离开作用域时会自动删除。范围由花括号{}
:
int* somefnc()
{
int e1
{
int* e2 = new int(0);
int e3 = 0;
} // int e3 gets automatically deleted here
return e2;
} // e1 gets automatically deleted here
// e2 still exists and has to be manually deleted.
指针的一个优点是处理数组时。如果要在堆栈上创建x元素的char数组,则必须在编译时知道元素的数量。如果要在运行时使用动态数量的元素创建x元素的char数组,则必须使用char* ar = new char[x];
,然后通过ar[x-1] = '\n';
访问它。
为了在堆上创建变量时初始化变量,您可以使用var x = new var(args);
。
答案 4 :(得分:0)
您可以将值作为参数传递给初始化堆中的内存。
int *iptr = new int(20);
初始化值为20;
stack:包含局部变量。因此,当您创建指针并为其指定本地对象时。它指向堆栈中的变量。我们不是在堆上创建指针