具有不可复制成员的复制赋值运算符
Posted
技术标签:
【中文标题】具有不可复制成员的复制赋值运算符【英文标题】:Copy assignment operator with non-copyable members 【发布时间】:2021-11-25 04:36:01 【问题描述】:假设我有一个只有构造函数的类A
:
struct A
A() = default;
A(const A&) = delete;
A& operator=(const A&) = delete;
;
我还有一个类B
,其中包含A
的一个实例,并按如下方式定义了复制构造函数:
struct B
B() = default;
B(const B& other) : _a
A _a;
;
这里B
的构造函数只是用A
的新实例初始化_a
。但是,我如何为B
编写赋值运算符(因为我不能“重新初始化”_a
)?
【问题讨论】:
应该会发生什么?如果赋值运算符存在,是否可以给A
提供类似于reset
的方法,相当于调用operator=(A)
?
您有几个选择:(1) 忽略_a
,在复制B
时不理会它。 (2) 使B
不可复制。 (3) 间接持有嵌入的A
实例,例如unique_ptr<A>
而不是A
,所以可以重制。
您可以尝试调用_a.~A()
并使用放置new
替换_a
(new (&_a) A
)。但是这个解决方案有一些微妙的问题,特别是A
构造函数不是noexcept
。而且由于A
似乎不可移动,它可能代表了一种不寻常的资源并且并非微不足道。我会考虑使用std::unique_ptr<A> _a;
而不是直接使用A
。
也许我可以让 A “可移动”并为 B 的赋值运算符使用交换习语(因为 B 的复制构造函数存在)?
【参考方案1】:
如果您希望operator=
创建一个类似于复制构造函数的全新A
,并且如果动态分配可行,您可以使用std::unique_ptr<A>
作为成员:
struct A
A() = default;
A(const A&) = delete;
A& operator=(const A&) = delete;
;
struct B
B() : _astd::make_unique<A>()
B(const B& other) : _astd::make_unique<A>()
B& operator=(const B& other)
_a = std::make_unique<A>();
return *this;
std::unique_ptr<A> _a;
;
不过,如果B
有一个不可复制(不可移动)的成员,那么最不令人惊讶的是B
也是不可复制(不可移动)的。
【讨论】:
运营商=你的意思是?【参考方案2】:根据类A
的定义,A
的实例是不可复制的,也是不可移动的。因此,我接受了@463035818_is_not_a_number 的回答。
这是另一个答案,它假设 A
可以移动,只是为了完整性或可能对某人有用。
struct A
A() = default;
A(const A&) = delete;
A& operator=(const A&) = delete;
A(A&&) = default;
A& operator=(A&&) = default;
;
struct B
B() = default;
B(const B&) : _a
B& operator=(B other)
std::swap(_a, other._a);
return *this;
A _a;
;
【讨论】:
以上是关于具有不可复制成员的复制赋值运算符的主要内容,如果未能解决你的问题,请参考以下文章