C++ 实例化没有'new'关键字的类会导致在堆栈或堆上创建其内部变量吗?

C++ 实例化没有'new'关键字的类会导致在堆栈或堆上创建其内部变量吗?,c++,class,memory-management,stack,heap,C++,Class,Memory Management,Stack,Heap,(在C++中)如果在类的构造函数中使用new关键字定义内部变量,则在不使用new关键字的情况下实例化类会导致在堆栈上创建其内部变量,还是会在堆上创建 换句话说,如果我们有一个类或结构,其中包含一个使用new关键字在其构造函数中定义的变量(例如数组),那么在不使用new的情况下创建该类的实例是否会导致在堆栈上创建内部数组,或者堆?任何使用新建创建的内容都在堆上创建 不使用new实例化类将堆栈分配类对象。然而,它的数据成员可以根据实例化的方式进行堆栈分配,也可以不进行堆栈分配 顺便说一下,函数中的静

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


换句话说,如果我们有一个类或结构,其中包含一个使用
new
关键字在其构造函数中定义的变量(例如数组),那么在不使用
new
的情况下创建该类的实例是否会导致在堆栈上创建内部数组,或者堆?

任何使用
新建
创建的内容都在堆上创建

不使用
new
实例化类将堆栈分配类对象。然而,它的数据成员可以根据实例化的方式进行堆栈分配,也可以不进行堆栈分配


顺便说一下,函数中的
静态
变量也是堆分配的;这就是它们在函数调用之间保持值的方式。

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

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

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;
}
将在堆栈上分配一些_foo
。堆栈将至少增长
sizeof(Foo)
(这将至少有足够的空间来存储指向整数的指针(
sizeof(int*)

由于使用了
new
,堆中存储了
some\u other\u foo
。同样,至少会从堆中分配
sizeof(foo)

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

如果我们有一个包含变量的类或结构(一个 示例)在其构造函数中使用new关键字will声明 不使用新的原因创建此类的实例 要在堆栈或堆上创建的内部数组

是的,即使您在堆栈上创建了一个对象(不带
new
关键字),如果在类construcor中使用new,其内部数据也将在堆上分配(当placement 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;
    // ...
}
除了

  • 普通新(在堆上分配)
  • 放置新语法(已分配内存)
…使用
new
的另一个选项不一定涉及堆使用,这是通过重载操作符new和delete!)进行的自定义分配


结论(编辑评论)

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

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

这些新选项返回的地址可以存储在调用进程(堆栈、堆或数据段)的地址空间的任何地方。

静态变量不在堆上。它们是静态分配的(给定固定地址).初始化的
静态的
变量在数据段上,未初始化的变量在数据段上。bss@AlanStokes你是对的,
static
变量在数据段中。@Alan Stokes,你当然是对的(因此是尊敬的+1)但我要说的是,它们不是堆栈分配的——这是一个常见的误解。不是所有用new创建的东西都是在堆上创建的;placement new:
char buf[1024];string*p=new(buf)string(“hello”);你能不能更精确一点:指向对象的指针放在堆栈上,而不是对象本身。什么对象?我很精确:指针在堆栈上,数据在堆栈上。我认为,即使你在堆栈上创建对象,这也会产生误导。我指的是文本,而不是代码片段。@WolfP。我可能会重写答案,请给我一个提示,告诉我我需要什么即使你在堆栈上创建了一个对象,它的内部数据也会分配到堆上,如果使用new,并在第二个示例之前粘贴它,基本上就可以了。我认为核心消息应该更好地与备选方案的详细描述分开。可能重复@Suma我认为这肯定是错误的ot的副本。可能的打字错误:堆栈将增长,您肯定是指“堆(使用)增长”。@WolfP.,哇。修复。谢谢。我不相信有这样的事情。@AlanStokes那么这(上面第三点)只是一个误解?这会让我平静下来:)…@AlanStokes现在我删除了伪造的静态语法。指针当然可以存储在任何地方。
char buf[1024];
string* p = new (buf) string("on stack");  // pointer is on stack,
                                           // data on the stack