当删除对象时,复制已删除对象的对象如何?

问题描述 投票:0回答:4

我对复制对象的工作方式感到困惑。如果我复制对象,删除复制的对象会怎样?为什么?就我而言,由于删除了原始对象,我认为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;
}
c++ class
4个回答
1
投票

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之前有中间代码,您几乎肯定不会得到您想要的东西。

所以要小心指向被破坏的对象的指针。


1
投票

副本是一个新对象。它具有自己的内存和生命周期。动作也一样。假设您具有以下结构:

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个不同的内存地址。


0
投票

假设您有一张纸。

现在,拿另一张上面有编号的纸。

将号码复制到第一张纸上。

烧录复印的纸张。

您复印到的纸张是否发生了什么变化?没有;它独立于其他论文。这就是对象在C ++中的行为。 (引用与对象不同,但是示例中没有引用)。


0
投票

在main()中,当创建对象b1时,它将被放置在堆栈中。然后,在创建的范围内,创建一个新的对象b2,并将其放置在堆栈/ after / b1中。然后,您使用隐式赋值运算符,该运算符将对象b2的内部值复制到对象b1的内部值。最后,范围b2被删除,但b1仍然存在。因此,内部值仍将是您从b2复制的值。

所以您没有两个引用相同内存空间的对象,但是我们正在谈论两个单独的实体。

© www.soinside.com 2019 - 2024. All rights reserved.