移动涉及const unique_ptr的构造函数
Move constructor involving const unique_ptr
在下面的代码中,我将p设为const,因为在Foo的生命周期中,它永远不会指向任何其他int。这不会编译,因为unique_ptr的复制构造函数被调用,它显然被删除了。除了使p非常量之外,还有什么解决方案吗?谢谢
#include <memory>
using namespace std;
class Foo
{
public:
//x is a large struct in reality
Foo(const int* const x) : p(x) {};
Foo(Foo&& foo) : p(std::move(foo.p)) {};
private:
const unique_ptr<int> p;
};
move构造函数的语义是矛盾的。
您已经声明了一个const std::unique_ptr
,它将(唯一)拥有初始化时使用的值。但是您已经声明了一个移动构造函数,该构造函数应该在构造时将该值移动到另一个对象中。
那么,你认为std::unique_ptr
在"临时"中应该发生什么呢?
如果你想让它成为release()
,你就违反了它的const
性。如果你想让它保持它的值,你就违反了std::unique
的约束,CCD_5要求不超过一个这样的对象来拥有任何给定的对象。Checkmate
这个问题揭示了C++语言的一个微妙的局限性。它要求move
语义将复制到的和作为有效对象。
对于"破坏性移动",有几个非常合理的建议,事实上,这些建议会更好地反映move
的大多数用途正在做的事情——从那里"失效"现有的东西。
用谷歌搜索。我还没有做过文献调查,所以不想推荐一个。
您的备选方案是删除const
或强制执行。我强烈建议删除它。你可以确保类的语义确保适当的常量,没有影响,也没有"丑陋的可疑"const_cast
。
#include <iostream>
#include <memory>
class Foo
{
public:
Foo(const int x) : p(new int(x)) {};
Foo(Foo&& foo) :
p(std::move(foo.p)) {
};
int get(void)const{
return *(this->p);
}
private:
std::unique_ptr<int> p;
};
Foo getMove(){
return Foo(88);
}
int main(){
Foo bar(getMove());
std::cout<<bar.get()<<std::endl;
return EXIT_SUCCESS;
}
要了解代码不编译的原因,请反映您是如何声明Foo
类的,以及move semantics
通常是如何实现的。
声明const unique_ptr<T> p
意味着p
本身永远不会被修改,但您仍然可以修改指向的对象,因为T
不是常量。
但move
的工作原理与此相反。该功能使用了允许从对象中窃取资源并使其处于空状态的思想(如果空状态有意义的话)。如果有用的话,可以将move
视为移动对象的一种"破坏性"副本。
编写std::move(foo.p)
,基本上就是窃取foo.p
指向的资源,并将其保持在安全状态,也就是说将foo.p
分配给NULL
。但是foo.p
被声明为const,因此不允许执行该操作。
请考虑,在您的情况下,您不需要将p声明为const unique_ptr<int>
。只需将其声明为unique_ptr<int>
,并确保成员函数声明为CCD24,而非成员函数将其作为const unique_ptr<int> p&
参数。通过这种方式,您可以确保p
在对象生存期内永远不会更改(移动操作除外)。
这是因为unique_ptr
只有move构造函数,这意味着p
的初始化参数不能是const,而p
是const。我想你想要的是申报
unique_ptr p;
而不是
const unique_ptr p;
class Foo {
public:
// x is a large struct in reality
Foo(const int* const x) : p(x) {};
Foo(Foo&& foo) : p(std::move(foo.p)) {};
private:
const unique_ptr<int> p;
};
使用std::unique_ptr的概念表示对象的唯一所有权。您试图实现的是让Foo类拥有一个对象(用std::unique_ptr表示)和使其可移动(您的移动构造函数),这会产生矛盾。我会坚持使用std::unique_ptr,或者使用std::shared_ptr进行共享。
您可能想阅读以下内容:聪明的指点者:或者谁拥有你的孩子?
如果要防止所有权转移,可以使用const std::unique_ptr<T>
。这不是很有用。
如果要防止修改它所包含的对象,可以使用std::unique_ptr<const T>
。
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- 一对向量构造函数:初始值设定项列表与显式构造
- 从构造函数抛出异常时如何克服内存泄漏
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 具有默认模板类型的默认构造函数的类型推导
- 带智能ptr的Pimpl-为什么需要构造函数/析构函数
- 具有基类唯一ptr的类的复制构造函数
- 共享 PTR - shared_ptr 和 unique_ptr Lippman C++入门中的构造函数