这是我在stackoverflow上的第一个问题。如果这是一个“愚蠢”的问题,那么对不起,但是我正在学习C++,我有点困惑。根据我所理解的,在下面的代码中,变量“myVariable”在堆上声明但在构造函数中在栈上实例化。那么它在哪里“生活”-在堆上还是栈上?
class MyClass{
int _myVariable;
MyClass(int i){
_myVariable = i;
}
}
这是我在stackoverflow上的第一个问题。如果这是一个“愚蠢”的问题,那么对不起,但是我正在学习C++,我有点困惑。根据我所理解的,在下面的代码中,变量“myVariable”在堆上声明但在构造函数中在栈上实例化。那么它在哪里“生活”-在堆上还是栈上?
class MyClass{
int _myVariable;
MyClass(int i){
_myVariable = i;
}
}
void example() {
MyClass a{17}; // This allocates memory on stack
MyClass *b = new MyClass(17); // This allocates memory on heap
}
a
看起来像是一个全局变量,通常既不在堆栈上也不在堆上。 - MSalters自动存储
和动态存储
。
最常用的变量存储实现分别是堆栈和堆。
new
操作符将对象存储在动态存储中:
MyClass* mc = new MyClass(14);
。
请注意,我们现在需要使用指针来访问它。MyClass mc = MyClass(14); // 在自动存储上构造一个对象
。MyClass
是多态的(也就是说,它具有虚函数),则无法将其放入自动存储中,因为编译器需要知道对象的大小。由于在多态性中,指向的对象的大小可能会在运行时发生变化,因此无法在自动存储中创建它。MyClass c = MyClass2(); //Object Slicing
c.foo(); // calls MyClass::foo()
MyClass* cc = new MyClass2(); //No Object Slicing
cc->foo(); // calls MyClass2::foo();
有一些辅助类可以帮助你摆脱清理内存的责任:unique_ptr
和 shared_ptr
(尽管后者很少使用)。
MyClass
对象放在自动存储中,而且你甚至展示了你可以这样做。而“对象的大小可以在运行时改变”是错误的;一个对象从其生命周期开始到结束都具有相同的大小。我理解你的意思,但我不是你的目标受众。 - MSaltersMyClass c
并非多态的,即使我尝试实例化MyClass2
,因为它调用的是MyClass :: foo()
而不是MyClass2 :: foo()
。 - RaildexMyClass :: foo
是virtual
,那么MyClass
是多态的。你可以切割MyClass2
,但这并不重要;一个类是否是多态的完全取决于标准规定。 - MSalters这得看对象存在的位置。如果实际对象在堆上,变量也在堆上。如果对象存在于栈上,则变量也存在于栈上。
看这个例子:
MyClass myObject = MyClass(5); // myObject lives on the stack and thus the variable i for myObject also lives on the stack
MyClass* newObject = new MyClass(5); // newObject is allocated on the heap and the variable i for newObject lives on the heap
delete newObject; // since newObject is created using new we must free the memory after use
MyClass
变量所在的位置。如果你使用new MyClass
,它会在堆中。如果你声明一个局部变量,它会在栈中。如果你声明一个全局变量,它会在数据段中。 - Barmar