C++ 移动包含常量唯一的构造函数\u ptr

C++ 移动包含常量唯一的构造函数\u ptr,c++,constants,move,unique-ptr,move-constructor,C++,Constants,Move,Unique Ptr,Move Constructor,在下面的代码中,我使用了p const,因为它在Foo的生命周期中永远不会指向任何其他int。这不会编译,因为调用了unique_ptr的copy构造函数,它显然被删除了。除了使p为非常量之外,还有什么解决方案吗?谢谢 #include <memory> using namespace std; class Foo { public: //x is a large struct in reality Foo(const int* const x) : p(x) {};

在下面的代码中,我使用了p const,因为它在Foo的生命周期中永远不会指向任何其他int。这不会编译,因为调用了unique_ptr的copy构造函数,它显然被删除了。除了使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;
};
#包括
使用名称空间std;
福班
{
公众:
//x实际上是一个大结构
Foo(const int*const x):p(x){};
Foo(Foo&&Foo):p(std::move(Foo.p)){};
私人:
const unique_ptr p;
};

如果要阻止所有权转让,可以使用
const std::unique\u ptr
。这不是很有用


如果要防止修改其持有的对象,可以使用std::unique\u ptr使用std::unique\u ptr的概念表示对象的唯一所有权。您试图实现的是让一个Foo类拥有一个对象(由std::unique_ptr表示)并使其可移动(您的移动构造函数),这会产生矛盾。我会坚持使用std::unique\u ptr,或者使用std::shared\u ptr将其共享

您可能需要阅读以下内容:
移动构造函数的语义是矛盾的

您已经声明了一个
const std::unique_ptr
,它将(唯一地)拥有初始化时使用的值。 但是您已经声明了一个move构造函数,它应该在构造时将该值移动到另一个对象中

那么,您认为要从中构造的“临时”中的std::unique\u ptr应该发生什么变化呢

如果你想让它
release()
ed,你就违反了它的
const
ness。 如果您希望它保留其值,那么您违反了
std::unique
的约束,不需要超过一个这样的对象才能拥有任何给定的对象。 将死。

这个问题揭示了C++语言的一个微妙的局限性。需要
move
语义才能将复制到的对象作为有效对象

对于“破坏性移动”,有几个相当合理的建议,实际上,这些建议会更好地反映出
移动的大多数用途所做的事情-从这里取一个值,使那里的东西“无效”

谷歌他们。我还没有做过文献调查,所以我不想推荐一个

您可以选择删除
const
或强制转换它。 我强烈建议删除它。您可以确保类的语义确保适当的常量,不会产生任何影响,也不会出现“丑陋的嫌疑犯”
const\u 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(const int x):p(new int(x)){};
Foo(Foo&&Foo):
p(标准::移动(foo.p)){
};
int get(void)const{
返回*(此->p);
}
私人:
std::唯一的ptr p;
};
Foo getMove(){
returnfoo(88);
}
int main(){
Foo-bar(getMove());

std::cout要理解代码为什么不编译,请反映您是如何声明
Foo
类的,以及
move semantics
通常是如何实现的

声明一个
const unique\u ptr p
,您的意思是
p
本身永远不会被修改,但是您仍然可以修改指向的对象,因为
T
不是const

但是
move
的工作原理与此相反。此功能使用的思想是允许从对象中窃取资源并使其处于空状态(如果空状态有意义)。如果可能有用,请将
move
视为移动对象的一种“破坏性”拷贝

编写
std::move(foo.p)
,基本上就是窃取
foo.p
所指向的资源并将其保持在安全状态,这意味着将
foo.p
分配给
NULL
。但是
foo.p
被声明为const,因此该操作是不允许的

请考虑,在您的情况下,不需要声明P为“代码> const UngQuyPPT/<代码>。只需将其声明为<代码> UnQuyPPTR < /代码>,并确保成员函数被声明为<代码> const ,非成员函数将其视为


const unique\u ptr p&
参数。通过这种方式,您可以确保
p
在对象生存期内永远不会改变(移动操作除外).

这是因为
unique\u ptr
只有move构造函数,这意味着
p
的初始化参数不能是const,而
p
是const。我想你想要的是声明

独特的ptr p

而不是

const unique_ptr p

class-Foo{
公众:
//x实际上是一个大结构
Foo(const int*const x):p(x){};
Foo(Foo&&Foo):p(std::move(Foo.p)){};
私人:
const unique_ptr p;
};

你到底需要一个
const unique\u ptr
做什么?也许你想要一个
shared\u ptr
?我不“需要”它,但我想指出,p在Foo的生命周期中将指向同一个int。如果
p
永远不会指向另一个
int
那么为什么要使用指针而不是普通成员?在我的实际代码中,“x”是一个大的pod结构。我宁愿传递一个指针而不是复制/移动它。你可以将它设置为常量,不允许移动Foo,或者将其设置为非常量。很抱歉。它是如何产生矛盾的?它是一个移动,而不是一个副本?矛盾是对象的唯一所有权,并且移动它-实例化类Foo的对象后,它拥有一个“p”-以后无法移动,导致另一个对象拥有“p”,因为它属于上一个对象。我将如何使用
const_cast
?我尝试了
const_cast
,但收到一个编译错误:使用类型为“std::unique_ptr”的const_cast无效,它不是指针、引用,也不是指向数据成员类型的指针。我不允许使用它,但您要查找的代码是
p(std::move(const_cast(foo.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;
};