移动语义和对象类型参数

时间:2015-12-17 04:06:01

标签: c++ c++11 move-semantics

我正在阅读有关移动语义的this答案并提出问题。他描述了所谓的移动和交换习语:

unique_ptr& operator=(unique_ptr source)   // note the missing reference
{
    std::swap(ptr, source.ptr);
    return *this;
}

由于移动赋值运算符应该在 rvalue 引用上运行,我认为将rvalue引用作为参数传递是可以接受的。这是一个例子:

#include <iostream>

struct A {
    A(){ }
    virtual ~A(){ }
    A(A&&){ }
};

void foo(A a){
    std::cout << "foo(A)" << std::endl;
}

int main()
{
    foo(*new A);
}

DEMO

但编译器警告我它尝试复制引用的对象并失败,因为复制构造函数已被删除。我不赞成为什么在unique_ptr的示例中它是正确的。当我们调用函数时,该对象应该是 复制 ,因此 移动 语义没有意义。< / p>

你能解释一下吗?

2 个答案:

答案 0 :(得分:4)

表达式*(new A)不是右值。

对于什么表达式是rvalues的一般规则(不是the actual rule,只是一个快速)是:它是临时的或者你明确地调用std::move的东西。并且*(new A)不是暂时的。你没有打电话给move。所以它不是右值。

请改为使用A()

答案 1 :(得分:2)

调用move构造函数从同一类型的 rvalue 构造一个新对象。如果您尝试将左值传递给按值采用仅移动类型的函数,则需要 copy 构造函数,否则您将收到错误。< / p>

void f(std::unique_ptr<Foo> p);
std::unique_ptr<Foo> p;
f(p);  // error
f(std::move(p));  // OK

在您的示例中,可以执行此操作:

foo(std::move(*new A));

但仅*new A不是可能的参数,因为取消引用指针总会产生左值。