5

我正在学习 C++,我有一个关于指针的问题。

我有这个代码:

int* max = new int;
*max = 0;

我想,我在堆上创建了一个指针(如果我不对,请告诉我)。

一个问题:

有没有办法用一条指令创建一个初始化指针?(现在,我使用了两条指令)。

另一个问题:

如何在堆栈上创建指针?

我看到这样的代码:

int myVar = 20;
int* pVar = &myVar;

我想我没有在堆栈上创建指针,但我认为这是不在堆上创建指针的唯一方法。

我对 C++ 开发非常非常陌生。

4

5 回答 5

11

指针是普通变量,其内容是内存地址。该内存可以是堆内存或堆栈内存。不要将指针与其指向的内存空间混淆。

您的第一个代码在可以容纳 int的堆上分配空间。您将指向该内存的指针存储在堆栈上

您的第二个代码在堆栈上分配可以容纳 int 的空间。您将指向该内存的指针存储在堆栈上

所以两个指针都在堆栈上,但只有第二个指向堆栈

在这两种情况下,您分配的类型都是原始类型。默认情况下不会初始化原始类型,除非您立即为其分配一个值(您的第二个代码),或者使用构造函数语法,该语法也适用于堆分配的值:

int *max = new int(0);

顺便说一句,可以在您的第二个代码中使用相同的语法:

int myVar(20);

如果您有兴趣:您还可以在堆上定义指针。int*是指向ints 的指针的类型,所以继续在堆上分配这样的类型:

new int*();

此表达式返回一个int**,然后您可以将其存储在某处。同样,您通常将此指向指针的指针存储在堆栈中:

int **pointerToPointer = new int*();

ints 一样,您可以将 new 表达式中的 an 初始化int*为某个指向 int 的指针(这里是max上面的指针):

int **pointerToPointer = new int*(max);

现在您有两个具有相同地址的max指针:(堆栈上的指针)和您指向 using 的堆上的一些指针pointerToPointer,即以下持有(我取消引用`pointerToPointer,这导致存储在此指针后面的值,即一个指向 int 的指针):

max == *pointerToPointer
于 2013-05-25T13:26:39.467 回答
11
int* max = new int;

上面的行在堆栈上创建了一个指针,并使用存储在堆中的整数对其进行初始化。每当new涉及到表达式时,它都会返回一个指向其动态创建的操作数的指针:

根据 C++11 标准的第 5.3.4/2 段:

-表达式创建的实体new具有动态存储持续时间 (3.7.4)。[ -- ]如果实体是非数组对象,则 new 表达式返回一个指向所创建对象的指针。如果它是一个数组,则new- 表达式返回一个指向数组初始元素的指针。

int myVar = 20;
int* pVar = &myVar;

在此示例中,指针及其值都存储在堆栈中。new分配中不涉及 - 表达式,因此在这种情况下不会在堆上创建任何内容。

如果要在一行中初始化指向对象的值,则必须像这样对其进行值初始化:

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);
于 2013-05-25T13:32:00.610 回答
2

有没有办法用一条指令创建一个初始化指针?

是的:

int * a = new int(20); //initialized with 20;

如何在堆栈上创建指针?

int myVar = 20;
int* pVar = &myVar;    //copied your code snipped It's alright
于 2013-05-25T13:27:49.410 回答
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);.

于 2013-05-25T13:36:13.847 回答
0

您可以将值作为参数传递以初始化堆中的内存。

 int *iptr = new int(20);

它用值 20 初始化;

堆栈:包含局部变量。因此,当您创建指针并为其分配本地对象时。它指向堆栈中的变量。我们没有在堆上创建指针。

于 2013-05-25T13:24:20.200 回答