【问题标题】:C++ Smart Pointer Lost in std::make_uniqueC++ 智能指针在 std::make_unique 中丢失
【发布时间】:2019-03-14 02:12:53
【问题描述】:

我正在转换一些遗留代码以利用 C++ 中的智能指针。但是,我遇到了一个我正在努力解决的运行时问题。我有如下代码:

struct foo {
    int field;
};

class SomeClass {
private:
    std::unique_ptr<foo> m_Foo;
    int m_Field;
public:
    SomeClass(std::unique_ptr<int> ctorArg)
        : m_Field(ctorArg->field), m_Foo(std::move(ctorArg)) {
    }
};

std::unique_ptr<foo> fooPtr{ new foo() };
auto const classInstance{ std::make_unique<SomeClass>(std::move(fooPtr)) };

如果我在调用SomeClass 构造函数之前放置一个断点,我可以验证fooPtr 不为空。然而,一旦我在SomeClass 构造函数中,应用程序在尝试初始化m_Field 时崩溃,因为ctorArg 为空(空)。这是预期的吗?如果我将构造函数签名更改为采用std::unique_ptr&lt;int&gt; &amp;&amp;,我会看到同样的问题。谁能解释一下这段代码有什么问题,以及如何修复它?

【问题讨论】:

  • 您只能拥有一个 unique_ptr(一种所有权)。当你移动它时,你正在传递这个所有权,所以后面被分配为 nullptr
  • 不幸的是,您的代码有两个名为 ctorArg 的变量,因此您在说的是哪个变量并不完全清楚。如果您谈论的是第二次出现,那么这是 unique_ptr 的预期行为。
  • 我已更新代码以使用单独的变量名称,因为@Amadeus 评论表明该问题的原始措辞不清楚它所表现的行为。
  • @AhmedMasud no, std::unique_ptr&lt;int&gt; intPtr { new int() }; 创建一个动态的int,并初始化intPtr。您的 sn-p 不是有效的 C++

标签: c++ smart-pointers unique-ptr


【解决方案1】:

member-initializer-list 的顺序无关紧要,成员将按照其声明的顺序进行初始化。

因此,首先m_Foo(std::move(ctorArg)) 将清零ctorArg 然后 m_Field(ctorArg-&gt;field) 将尝试取消对空ctorArg 的引用。

将您的代码更改为:

class SomeClass {
private:
    std::unique_ptr<foo> m_Foo;
    int m_Field;
public:
    SomeClass(std::unique_ptr<int> ctorArg)
        : m_Foo(std::move(ctorArg)), m_Field(m_Foo->field) {
    }
};

也就是说,始终按照声明字段的顺序提及初始化器,并且不要使用已移出的输入参数。

【讨论】:

  • 顺序问题仅适用于全局变量位于不同源文件中的情况。
  • @rustyx 我已经更新了示例代码,所以它现在实际上打破了我观察的方式。
猜你喜欢
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-12
相关资源
最近更新 更多