我对复制对象的工作方式感到困惑。如果我复制对象,删除复制的对象会怎样?为什么?就我而言,由于删除了原始对象,我认为b1.test
是不确定的。
class blog
{
public:
int test;
blog() = default;
blog(int input) :test(input) {}
};
int main()
{
blog b1;
{
blog b2 = 1;
b1 = b2;
std::cout << b1.test << std::endl;
}
std::cout << b1.test << std::endl;
}
Quentin给您简单的答案。副本是副本。想象一下,如果您这样做:
int a;
{
int b = 3;
a = b;
}
cout << a << endl;
即使b不存在,您也会得到3。这是因为a是b的副本。
在您的代码中,您正在做相同的事情,只是您正在复制整个对象,而不仅仅是一个简单的整数。
请记住,如果对象很复杂,则复制对象可能会很昂贵。
但是请注意,如果您保留指针,则完全不同,如下所示:
int * a = nullptr;
{
int b = 3;
a = &b;
}
cout << "A: " *a << endl;
在这一点上,您将可能获得预期的结果,因为这是一个简单的问题,但是,这确实是很顽皮的,因为它指向不再与某物相关联的某个随机存储位置。如果cout之前有中间代码,您几乎肯定不会得到您想要的东西。
所以要小心指向被破坏的对象的指针。
副本是一个新对象。它具有自己的内存和生命周期。动作也一样。假设您具有以下结构:
struct my_object
{
std::string m_name;
my_object(const std::string &name) :
m_name{name}
{
std::cout << m_name << " constructed: " << this << '\n';
}
my_object(const my_object &o) :
m_name{"copied " + o.m_name}
{
std::cout << m_name << " constructed: " << this << '\n';
}
my_object(my_object &&o) :
m_name{"moved " + o.m_name}
{
std::cout << m_name << " constructed: " << this << '\n';
}
~my_object()
{
std::cout << m_name << " destructed: " << this << '\n';
}
};
如果您执行以下操作:
auto
main() -> int
{
my_object o1{"o1"};
my_object o2{"o2"};
{
auto o3 = o1;
auto o4 = std::move(o2);
}
return 0;
}
您得到:
o1 constructed: 0x7ffe72e0f450
o2 constructed: 0x7ffe72e0f430
copied o1 constructed: 0x7ffe72e0f3f0
moved o2 constructed: 0x7ffe72e0f410
moved o2 destructed: 0x7ffe72e0f410
copied o1 destructed: 0x7ffe72e0f3f0
o2 destructed: 0x7ffe72e0f430
o1 destructed: 0x7ffe72e0f450
如上所述,我们创建了4个不同的对象,每个对象都有自己的生命周期,所以我们有4个不同的内存地址。
假设您有一张纸。
现在,拿另一张上面有编号的纸。
将号码复制到第一张纸上。
烧录复印的纸张。
您复印到的纸张是否发生了什么变化?没有;它独立于其他论文。这就是对象在C ++中的行为。 (引用与对象不同,但是示例中没有引用)。
在main()中,当创建对象b1时,它将被放置在堆栈中。然后,在创建的范围内,创建一个新的对象b2,并将其放置在堆栈/ after / b1中。然后,您使用隐式赋值运算符,该运算符将对象b2的内部值复制到对象b1的内部值。最后,范围b2被删除,但b1仍然存在。因此,内部值仍将是您从b2复制的值。
所以您没有两个引用相同内存空间的对象,但是我们正在谈论两个单独的实体。