提问人:mercury0114 提问时间:1/15/2023 最后编辑:mercury0114 更新时间:1/16/2023 访问量:94
当类具有 const std::unique_ptr 类型的成员时,您能否设计一个构造函数以允许“类 c(std::move(another_class))”?
Can you design a constructor to allow `Class c(std::move(another_class))` when the class has a member of type const std::unique_ptr?
问:
下面是我尝试设计的类的简化版本
class Class {
public:
Class(std::unique_ptr<int>&& ptr): ptr_(std::move(ptr)) {}
private:
// works only if I change to std::shared_ptr or remove const qualifier
const std::unique_ptr<int> ptr_;
};
int main() {
std::unique_ptr<int> ptr = std::make_unique<int>(1);
Class c(std::move(ptr)); // Compiles
// I need to construct a new instance d, but c is not needed anymore,
// anything c owns can be nullified.
Class d(std::move(c)); // Does not compile
return 0;
}
由于以下错误消息,我无法从实例构造实例:d
c
“Class”的复制构造函数被隐式删除,因为字段“ptr_” 具有已删除的复制构造函数
但是,如果我将成员更改为 类型 ,那么一切正常。ptr_
const std::shared_ptr<int>
有没有办法为 ,它支持:Class
- 构造类实例,直接提供它需要的参数
- 从另一个类实例构造类实例,可能会破坏进程中的另一个实例(即 c(std::move(d));
- 允许类具有 type 的成员
const unique_ptr
?
编辑:使用构建实例也不起作用:d
std::move(c)
class.cc:17:23:错误:使用已删除的函数“Class::Class(Class&&)” 17 |类 d(std::move(c)); |^ class.cc:5:7: 注意: 'Class::Class(Class&&)' 被隐式删除,因为默认的 定义格式不正确:
到目前为止,有两个解决方案对我有用,从可读性的角度来看,两者都不是完美的:
删除限定符:
const
std::unique_ptr<int> ptr_
;问题在于,这读作:“调用公共方法时,ptr_成员可能会被修改”
对共享指针的更改:
const std::shared_ptr<int> ptr_
;问题在于,这读作:“我们有多个指针指向相同的数据”
有什么方法可以改进设计,而不会出现(1)和(2)中概述的问题?
答:
- 从另一个类实例构造类实例,可能会破坏过程中的另一个实例(即
c(std::move(d)
);- 允许类具有 type 的成员
const unique_ptr
这种欲望的交集本质上是矛盾的。
移动是一种修改操作。如果对象是 ,则无法从中移动。const
其全部目的是程序中有一个实例,它唯一地拥有(并将销毁)它所指向的对象。因此,它不能被复制,因为复制是一个非修改操作。如果可以复制它,那么两个对象将尝试拥有同一个对象。unique_ptr
您不能从 .您不能从任何类型的对象移动。因此,如果对象具有 ,则无法从该对象的其他实例中获取指针。unique_ptr
const
const unique_ptr
通过声明成员为 ,您还声明该对象既不能复制也不能移动。这些是代码选择的后果。const unique_ptr<T>
因此,您将不得不决定什么更重要:成员是或从该对象复制/移动的能力。const
从广义上讲,成员创造的问题比他们通常解决的问题要多。如果成员是私人的,那么这通常就足够了;直接访问该类的用户应该能够知道每个此类函数应该修改什么,不应该修改什么。如果他们犯了一个错误,那么这个错误的代码就会非常有限。const
评论
Broadly speaking, const members create more problems than they usually solve
- 我不同意这种说法,但其余接受的答案是有道理的,谢谢!
评论
Is there a way to have a single constructor for the Class, which would support:
不。c
std::move(c)
c
Class d(std::move(c));
const
const
const