2

(在 C++ 中)如果在类的构造函数new中使用关键字定义它们,那么在不使用关键字的情况下实例化一个类会导致在堆栈上创建其内部变量,还是在堆上创建它们?new

换句话说,如果我们有一个包含使用new关键字在其构造函数内定义的变量(例如数组)的类或结构,将创建此类的实例而不使用new导致在堆栈上创建内部数组,或者堆?

4

5 回答 5

3

运算符 new 在堆中分配内存,除非您使用placement new 运算符,您可以在其中自己指向对象使用的内存。

于 2013-11-15T08:16:09.740 回答
3

如果我们有一个包含使用 new 关键字在其构造函数中声明的变量(例如数组)的类或结构,将在不使用 new 的情况下创建此类的实例,从而导致在堆栈或堆上创建内部数组?

是的,即使您在堆栈上创建一个对象(不带new关键字),如果在类构造函数中使用 new,它的内部数据也将在堆上分配(当放置 new 用于在堆栈上分配数据时可能会有例外 - 我们会看到它之后)。常见的例子是分配一个数组:

int main() {
    int* t = new int[100];  // pointer is on stack, data on the heap
    //...
}

同样:

class A{
public:
    A(){ 
        int* t = new int[100];
        std::cout<<"heap used\n";
        delete t;
    }
};

int main(int argc, char** argv) {

    A a1;
    // ...
}

印刷:

使用的堆

实际上,int在免费存储中已分配(并删除)了 100 个。


如果您需要指定内存位置,您可以使用placement new

char buf[1024];
string* p = new (buf) string("on stack");  // pointer is on stack,
                                           // data on the stack
于 2013-11-15T08:40:23.223 回答
3

考虑以下代码并假设没有优化:

struct Foo {
    int* pointer_to_int;

    Foo() : pointer_to_int(new int) { }
    ~Foo() { delete pointer_to_int; }
}

void func() {
    Foo some_foo;
    Foo* some_other_foo = new Foo;
}

some_foo将在堆栈上分配。堆栈将至少增长sizeof(Foo)(这将至少有足够的空间来存储指向整数 ( sizeof(int*)) 的指针。

some_other_foo由于使用 . 被存储在堆上new。同样,至少sizeof(Foo)会被分配,但这次是从堆中分配的。

在这int两种情况下,在 Foo 的构造函数中创建的 都将存储在堆中。这将至少增加堆的大小sizeof(int)

于 2013-11-15T08:34:20.167 回答
0

此外

  • 普通新(在堆上分配)
  • 放置新语法(已分配内存)

...还有另一个new不一定涉及堆使用的选项,即通过重载运算符 new和 delete!)来定制分配。


结论(编辑评论)

因此,即使使用 创建new,对象也可以驻留

  • 堆上(这是默认行为)
  • 在它所在的现有内存中(放置新语法)
  • 如果用户愿意,也可以在其他任何地方(通过重载 new

每个新选项返回的地址都可以存储在调用进程的地址空间(堆栈、堆或数据段)中的任何位置。

于 2013-11-15T10:17:27.123 回答
-1

用 anew创建的任何东西都是在堆上创建的。

在不使用的情况下实例化一个类new将堆栈分配类对象。然而,它的数据成员可能会也可能不会根据它们的实例化方式进行堆栈分配。

顺便说一句,static函数内的变量也是堆分配的;这就是他们能够在函数调用之间保持值的方式。

于 2013-11-15T08:13:25.107 回答