【问题标题】:When object variable is reassigned in C++, what happens to the original object?当在 C++ 中重新分配对象变量时,原始对象会发生什么?
【发布时间】:2015-02-14 03:45:52
【问题描述】:
在 C++ 中重新分配对象变量时,原始值会发生什么变化?
在下面的代码中,一个对象被创建到堆栈上并放置在变量中。然后在堆栈上创建一个新对象并放置在同一个变量中。原始对象会发生什么?在 variable 超出范围之前,它会一直留在堆栈中吗?
void foo() {
ClassName variable(a, b); // variable created on the stack
variable = ClassName(c, d); // new value for variable created on stack
...
}
【问题讨论】:
标签:
c++
memory
memory-management
stack
【解决方案1】:
发生的情况是调用了类的赋值运算符。在大多数情况下,这只意味着旧对象的内容会使用新对象的值进行更新。所以如果ClassName 是:
struct ClassName
{
int a;
int b;
ClassName(int a, int b) : a(a), b(b) {}
};
在这种情况下,将调用默认的赋值运算符,相当于:
ClassName& operator=(const ClassName& other)
{
a = other.a;
b = other.b;
return *this;
}
对于具有动态内容的类,需要做更多的工作,但结果通常是相同的。由于赋值运算符可以被覆盖,理论上任何事情都可能发生,但这是我们所期望的。
【解决方案2】:
实际上,对象没有任何反应:你还在使用它!
赋值不会用不同的对象替换整个对象:它调用原始对象的赋值运算符,允许对象使它看起来像新的东西,即使它不是。
例如:
int x = 1;
x = 2;
您在这里只声明了 一个 对象,即使它的值发生了变化。
当然,即使在这个简单的 sn-p 中,也确实有多个对象在起作用——1 和 2 都是整数文字和临时对象。但是,您问的不是这些。它们的值被复制到x。
同样,在您自己的代码中,您将临时ClassName(c, d) 的“值”复制到variable,但variable 仍然是原始variable。
临时的ClassName(c, d) 在您使用它的行的末尾超出范围;用于表示它的字节(除非已优化)可能会驻留在堆栈帧中,直到您离开函数范围,尽管您将无法合法地读取它们。
【解决方案3】:
从技术上讲,operator= 由赋值的左侧部分调用,例如
variable.operator=(ClassName(c,d));
在您的情况下,如果您没有明确定义赋值运算符,编译器会为您生成一个默认值,它使用其各个成员的复制赋值运算符复制右侧。因此左侧(即您的情况下为variable)被修改,其各个成员是右侧临时成员的副本。