【问题标题】:Why can I copy std::unique_ptr into another one without using std::move?为什么我可以在不使用 std::move 的情况下将 std::unique_ptr 复制到另一个?
【发布时间】:2020-06-15 05:26:01
【问题描述】:

除非你使用 std::move,否则不应将 std::unique_ptr 复制到另一个 std::unique_ptr,对吗?

但我经历过这样的事情。

#include <iostream>
#include <memory>

using namespace std;


class ClassA{
public:

    ClassA() {
        cout << "created" << endl;
    }

    ~ClassA() {
        cout << "destroyed" << endl;
    }



    void print() {
        cout << "ok" << endl;
    }

};

void test() {

    unique_ptr<ClassA> b(new ClassA());

    b->print();

    // unique_ptr<ClassA> d(b); this won't compile since you can't copy unique_ptr

    ClassA& aa = *b;  // ClassA aa = *b; works too.

    unique_ptr<ClassA> d(&aa); // but this can, why is that

    d->print();
}

int main(int argc, char *argv[])
{

    test();

    return 0;
}

程序运行正常,输出为:

created
ok
ok
destroyed
destroyed

ClassA 被摧毁了两次,这是怎么回事?它应该因为没有可删除的内容而崩溃吗?

【问题讨论】:

  • 想想名字。如果你可以复制一些东西,它仍然是独特的吗?
  • ClassA aa = *b; 会有所不同——然后d 指的是自动存储,并且在尝试删除该存储时会导致未定义的行为。两种情况都是UB,但原因不同

标签: c++ std unique-ptr


【解决方案1】:

当您执行std::unique_ptr&lt;ClassA&gt; d(&amp;aa); 时,您正在使用原始指针创建dunique_ptr 构造函数看不到您正在向它传递一个指向已由另一个 std::unique_ptr 拥有/管理的对象的指针。

因此导致双重删除,这会导致未定义的行为,即任何事情都可能发生。

【讨论】:

  • 我现在明白了。我担心的一个问题是双重删除不会崩溃或产生任何问题,那么这个错误如果写出来就很难被发现。
  • @xkimi 在初始化命名引用时,您总是需要考虑对象的生命周期。引用可能比其生命周期以不同方式控制的原始对象的寿命更长
  • @M.M 我发现了一些有趣的东西。对象获取重置()后我仍然可以调用 print()
  • @xkimi 未定义行为意味着任何事情都可能发生
  • 此外,您的打印不会以任何方式引用对象,因此不太可能崩溃。如果你有一个成员变量并打印它,它可能会崩溃,但作为 UB,它可能会工作,或者可能会打印一些垃圾值......
猜你喜欢
  • 2019-07-09
  • 2014-11-11
  • 2017-06-11
  • 2020-12-05
  • 2013-05-18
  • 2015-10-14
  • 2016-07-16
  • 1970-01-01
  • 2018-04-17
相关资源
最近更新 更多