首页 > 解决方案 > 如何按值传递只移动类型(例如 std::unique_ptr)?

问题描述

如果我们std::unique_ptr举个例子,将只移动类型传递给接收器函数(例如,获取指针所有权的构造函数)的普遍智慧是按值传递它并在调用站点移动它。例如

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

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

这怎么可能?编译器不应该能够立即推断出这std::unique_ptr是一个仅移动类型并拒绝使用Sink(std::unique_ptr<Foo>)吗?这里的按值传递规则有什么特别之处吗(即按值传递的东西被复制到该函数激活框架中)?

提前致谢。

标签: c++smart-pointersmove-semanticspass-by-value

解决方案


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

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

#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!
}

活在魔杖盒上


推荐阅读