【问题标题】:make_unique cannot access private constructor in static membermake_unique 无法访问静态成员中的私有构造函数
【发布时间】:2020-12-14 09:40:13
【问题描述】:

我的班级结构如下:

class S {
  public:
    S() {}
};

class T {
  private:
    std::unique_ptr<S> a;
    T(S);

  public:
    static std::unique_ptr<T> make_item() {
        std::unique_ptr<S> s_instance = std::make_unique<S>();
        return std::make_unique<T>(std::move(s_instance));
    }
};

但是,当我尝试在 make_item 中创建一个 unique_ptr 时,它会将构造函数视为私有的。

有没有办法允许在类本身的静态成员函数中使用私有构造函数?因为一个成员是 S 的 unique_ptr(一个相当重的对象),我们不希望使用副本。

【问题讨论】:

  • 我支持重复的命题,但 std::make_unique 可以替换为 std::unique_ptr&lt;X&gt;(new X); 而不会造成任何性能损失,因此不需要该问题的技巧。
  • @Yksisarvinen 但这不是例外安全的!如果这个约束是相关的,工厂模式是更好的方法。
  • @Yksisarvinen “没有任何性能损失”是指不考虑额外分配?

标签: c++ unique-ptr


【解决方案1】:

正如 yksisarvinen 在 cmets 中提出的,解决此问题的一种方法是将 make_unique&lt;T&gt; 替换为 std::unique_ptr&lt;T&gt;(new T(S))

class S {
  public:
    S() {}
};
class T {
  private:
    std::unique_ptr<S> a;
    T(S);

  public:
    static std::unique_ptr<T> make_item() {
        // Create S
        std::unique_ptr<S> s_instance = std::make_unique<S>();
        return std::unique_ptr<T>(new T(s_instance));
    }
};

【讨论】:

  • 回答你自己的问题很好,但请注意问题有点不清楚。建议你把缺少的;S的声明和错误信息加上,这样别人才能真正看到问题
  • 那么在这里使用 std::make_unique 有什么好处呢?我们使用 if 是为了它的安全性,这不是“新”提供的。我认为可以在这里找到更好的答案:stackoverflow.com/questions/50995599/…
【解决方案2】:

可以将 make_unique 及其内部助手(如果有)声明为友元函数,这会使代码不可移植(如此处所述:How to make std::make_unique a friend of my class

或者将构造函数设为公开,但在其参数中添加一个私有元素,例如:

class S {
  public:
    S() {}
};

class T {
  private:
    struct Private
    { 
      friend T;
      private:
        explicit Private() = default; 
    };

    std::unique_ptr<S> a;

  public:
    T(S s, Private);

    static std::unique_ptr<T> make_item() {
        auto s_instance = std::make_unique<S>();
        return std::make_unique<T>(std::move(s_instance), Private());
    }
};

【讨论】:

  • 您可以使用密码习语来避免让任何人在您的类型上生成唯一性:stackoverflow.com/a/29897660/874660
  • 感谢您介绍“Passkey Idiom”这个词,我不知道这个词。我理解正确吗?这是我提供的答案的一般概念吗?
  • 不,让 make_unique 成为朋友的问题在于,任何人都可以 make_unique 所以它或多或少和公共 c'tor 一样好。使用 pass key 习惯用法,您有一个公共 c'tor 但其中一个参数是只有您的类可以创建的类型,因此 c'tor 与您的 API 一样私有,但您可以允许其他参数(例如make_unique) 通过传递 make_unique 一个 passkey 类的实例来调用它。
猜你喜欢
  • 2017-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
  • 1970-01-01
  • 2021-08-29
  • 2014-06-13
  • 1970-01-01
相关资源
最近更新 更多