【问题标题】:Late non-copyable member initialization后期不可复制成员初始化
【发布时间】:2015-10-16 23:42:22
【问题描述】:

我正在尝试初始化一个无法分配或复制的对象成员。我需要先执行一些其他任务,并且初始化依赖于它,所以我必须延迟它。

#include <boost/process.hpp>

class A{
    std::unique_ptr<boost::process::child> child_;
    std::unique_ptr<boost::process::pistream> is;

    A(std::string exec, boost::process::context process_context){
        // Stuff that needs to be done first
        // ...

        child_ = std::make_unique<boost::process::child>(start_child(exec, process_context));
        is = std::make_unique<boost::process::pistream>(child_->get_stdout()); // <- error

    }

    boost::process::child start_child(std::string exec, boost::process::context process_context);
};

我从中得到的错误是:

错误 C2280: 'std::basic_ios>::basic_ios(const std::basic_ios> &)' : 试图 引用已删除的函数

如果我理解正确,则该行的某处正在发生副本,这是不允许的。 不需要唯一指针。我只是用它们来避免另一个错误(没有默认初始化),但我很乐意接受有或没有它们的建议。

【问题讨论】:

  • get_stdout 返回一个pstream&amp;child_ 拥有的对象的引用。您正在尝试复制不可复制的pstream。我想你可以存储一个(原始的、非拥有的)指针,或者只是删除is 并根据需要使用child_-&gt;get_stdout()

标签: c++ c++11 boost


【解决方案1】:

您可以像这样使用boost::optional&lt;&gt; 进行延迟初始化。

Live On Coliru

#include <memory>
#include <boost/optional.hpp>

struct pistream { };
struct child    {
    pistream& get_stdout() { return is; }
    pistream is;
};
struct context  { };

class A {
    std::unique_ptr<child> child_;
    boost::optional<pistream&> is;

    A(std::string, context) {
        // Stuff that needs to be done first
        // ...

        child_ = std::make_unique<child>();
        is     = child_->get_stdout();
    }
};

【讨论】:

  • 添加了一个完整的演示(在注意到哪个成员绑定到什么引用之后...)Live On Coliru
【解决方案2】:

问题是std::unique_ptr 想要pistream 的所有权,所以它试图获取一个副本,正如您所发现的那样,这是不允许的。如果您考虑一下,这是有道理的:您当然不希望 std::unique_ptr&lt;b::p::pistream&gt; 在其析构函数中删除 _child 的流。

最简单的解决方案是只使用常规的非拥有指针,例如:

class A{
    std::unique_ptr<boost::process::child> child_;
    boost::process::pistream* is = nullptr;

    A(std::string exec, boost::process::context process_context){
        // ...
        child_ = std::make_unique<boost::process::child>(start_child(exec, process_context));

        is = &child_->get_stdout();
    }
};

当然,您需要在实际使用之前检查is 是否不是nullptr,但unique_ptr 也是如此。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-15
    • 2020-01-29
    • 2013-08-12
    • 2019-08-25
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多