方法1
我有一个Foo类型,它内部包含一个std::mutex。
class Foo {
std::mutex m_;
};我又写了一个班吧。Bar将Foo作为成员和构造函数,如下所示(注意-这段代码没有编译):
class Bar {
Bar(Foo foo) : foo(foo) {}
...
private:
Foo foo;
};我的IDE抱怨:
对隐式删除的Foo复制构造函数的
调用。“Foo”的复制构造函数被隐式删除,因为字段'm_‘有一个已删除的复制构造函数
方法2
于是我试着做这样的任务:
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有一个已删除的复制构造函数和已删除的副本分配,所以我唯一的选择是在堆上构造它,然后通过间接(通过指针)工作吗?
对吗?还是我完全疯了?
发布于 2021-06-18 06:19:45
是因为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发布于 2021-06-18 06:37:36
如果您检查互斥锁是如何实现的,您将看到它的复制构造函数和复制赋值操作符被删除,但是移动构造函数和移动赋值操作符没有,这就是为什么您的智能指针示例工作的原因。
我唯一的选择是在堆上构造它,然后通过间接(通过指针)工作?
不,这不是唯一的方法。如果您将第一个示例稍微更改为使用引用,也可以使用引用(而且foo不是在堆上构造的):
class Foo {
std::mutex m_;
};
class Bar {
Bar(Foo& foo) : foo(foo) {}
private:
Foo& foo;
};https://stackoverflow.com/questions/68030097
复制相似问题