首页 > 解决方案 > 依赖项没有复制 ctor 或赋值运算符时的 C++ 初始化程序列表

问题描述

方法一

我有一些 Foo 类型,它内部包含一个 std::mutex。

class Foo {
  std::mutex m_;
};

我写了另一个类吧。Bar 有 Foo 作为成员和构造函数,如下所示(注意 - 此代码无法编译):

class Bar {
  Bar(Foo foo) : foo(foo) {}
...
private:
  Foo foo;
};

我的 IDE 抱怨:

调用 Foo 的隐式删除的复制构造函数。'Foo' 的复制构造函数被隐式删除,因为字段 'm_' 具有已删除的复制构造函数

方法二

所以我试着做这样的任务:

class Bar {
  Bar(Foo fooIn) { foo = fooIn; }
...
private:
  Foo foo;
};

但这也说明:

无法分配“Foo”类型的对象,因为它的复制赋值运算符被隐式删除

方法 3(使用指针)

我可以让它工作的唯一方法是这样的:

class Foo {
private:
    std::mutex m_;
};

class Bar {
    Bar(std::unique_ptr<Foo> fooIn) : foo(std::move(fooIn)) {}
private:
    std::unique_ptr<Foo> foo;
};

我了解智能指针有助于内存管理。但是让我们把这个功能放在一边。

在我上面的例子中,不使用智能指针和使用智能指针的主要区别在于智能指针具有间接性——它指向堆上的一个对象。对?

理解这一点的正确心智模型是什么?是不是因为 Foo 有一个已删除的复制构造函数和已删除的复制分配,所以我唯一的选择是在堆上构造它,然后通过间接(通过指针)工作?

那是对的吗?还是我完全关闭了?

标签: c++c++11smart-pointers

解决方案


是不是因为 Foo 有一个已删除的复制构造函数和已删除的复制分配,所以我唯一的选择是在堆上构造它,然后通过间接(通过指针)工作?

关闭,但不完全。

因为互斥体不可复制,所以默认情况下 Foo 也不可复制。您正在尝试复制,这是不可能的。

使用间接引用存储在别处的 Foo 是可能的。但是 Foo 没有必要拥有动态存储来实现这一点。不可复制性也不意味着需要间接……除非您想防止不可复制性传播到封闭类。

互斥锁唯一的构造函数是默认构造函数。因此,您可以合理地做的只是默认初始化 Foo。一个最小的例子:

struct Bar {
    Foo foo;
    // no need to declare the default constructor
    // it is generated implicitly
};

Bar bar; // this just works

推荐阅读