C++ 如何通过值传递仅移动类型(例如std::unique_ptr)?

C++ 如何通过值传递仅移动类型(例如std::unique_ptr)?,c++,smart-pointers,move-semantics,pass-by-value,C++,Smart Pointers,Move Semantics,Pass By Value,如果我们以std::unique_ptr为例,将move-only类型传递到sink函数(例如,拥有指针所有权的构造函数)的普遍做法是按值传递它,并在调用站点移动它。例如 class Sink { public: Sink(std::unique_ptr<Foo> foo) : foo(std::move(foo)) {} private: std::unique_ptr<Foo> foo; }; 类接收器{ 公众: S

如果我们以
std::unique_ptr
为例,将move-only类型传递到sink函数(例如,拥有指针所有权的构造函数)的普遍做法是按值传递它,并在调用站点移动它。例如

class Sink {
    public:
        Sink(std::unique_ptr<Foo> foo) : foo(std::move(foo)) {}

    private:
        std::unique_ptr<Foo> foo;
};
类接收器{
公众:
Sink(std::unique_ptr foo):foo(std::move(foo)){}
私人:
std::唯一的\u ptr foo;
};
这怎么可能?编译器不应该立即推断出
std::unique\u ptr
是只移动的类型,并拒绝使用
Sink(std::unique\u ptr)
?这里的按值传递规则有什么特别之处吗(即,按值传递的内容被复制到该函数激活框架中)


提前感谢。

当然可以,只要您将右值传递给Sink的构造函数或移动参数。在这两种情况下,参数都将调用move构造函数,而不是(已删除的)copy构造函数

注意:我不认为
std::move
在这里是个好主意,因为这样你的函数中就会有一个moved-from对象。静态分析可能会发现这一点,但这是bug的来源

#include <memory>

struct Foo {};

class Sink {
    public:
        Sink(std::unique_ptr<Foo> foo) : foo(std::move(foo)) {}

    private:
        std::unique_ptr<Foo> foo;
};

int main() {
    // rvalue
    Sink s(std::make_unique<Foo>());

    // std::move (can be dangerous)
    auto f = std::make_unique<Foo>();
    Sink ss(std::move(f));

    // By value is not allowed
    auto ff = std::make_unique<Foo>();
  //Sink sss(ff); // BOOM!
}
#包括
结构Foo{};
班级水槽{
公众:
Sink(std::unique_ptr foo):foo(std::move(foo)){}
私人:
std::唯一的\u ptr foo;
};
int main(){
//右值
Sink s(std::make_unique());
//std::移动(可能很危险)
自动f=std::使_唯一();
水槽ss(标准:移动(f));
//不允许使用“按值”
auto ff=std::使_唯一();
//下沉sss(ff);//轰!
}

foo
不需要复制到,也可以移动到中这很好,但不幸的是(或作为历史的一个怪癖)“可移动”概念是最近才出现的,必须固定在一种已经非常成熟的语言上。@vu1p3n0x这是这里缺少的洞察力,我一直认为通过值传递调用复制构造函数,尽管我现在知道这取决于调用站点传递的值的类型(不带移动构造函数的左值和右值的复制构造函数,带移动构造函数的右值的移动构造函数)。“从对象移动是未定义的行为”否,这是错误的。有几种方法可以使用调用UB的moved from对象,但非moved from对象也是如此。因此,更准确的说法是,pass by value并不总是调用复制构造函数,而是根据传入的值是左值还是右值引用来调用复制或移动构造函数?@AUD_FOR_IUV,正如您所看到的,它取决于值的类型。右值调用移动构造函数(如果有,否则为复制),左值调用复制构造函数。“从对象移动的状态不确定”这也是错误的。有从状态不确定的对象移动的,也有从状态不确定的对象移动的,还有从状态完全确定的对象(在
std
内部和外部)移动的
unique\u ptr
是其中一种类型,其对象从状态的移动是完全确定的。@Yakk好的,我肯定没有足够的语言律师来争论这个问题,所以我只是删除了这个子句子。我希望您同意,从它周围的物体移动是一个潜在的bug来源。