移动语义和对象类型参数
Move semantic and an object-type parameter
我正在阅读 this 关于移动语义的回答并提出了一个问题。他描述了所谓的移动和交换成语:
unique_ptr& operator=(unique_ptr source) // note the missing reference
{
std::swap(ptr, source.ptr);
return *this;
}
由于移动赋值运算符应该对 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);
}
但是编译器警告我它试图复制引用的对象但失败了,因为复制构造函数被删除了。我不明白为什么在 unique_ptr
的示例中它是正确的。当我们调用函数时,对象应该被 copied,所以 move语义化。
你不能解释一下吗?
调用移动构造函数从相同类型的 rvalue 构造新对象。如果您尝试将 lvalue 传递给按值采用仅移动类型的函数,则它需要 copy 构造函数,您将得到一个错误。
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
本身不是一个可能的参数,因为解引用指针总是会产生一个左值。
表达式 *(new A)
不是右值。
关于什么表达式是右值的一般规则(不是 the actual rule,只是速记)是这样的:它要么是临时的,要么是您明确调用 std::move
的东西。而且 *(new A)
不是临时的。而且你没有在上面调用 move
。所以它不是右值。
尝试使用 A()
代替。
我正在阅读 this 关于移动语义的回答并提出了一个问题。他描述了所谓的移动和交换成语:
unique_ptr& operator=(unique_ptr source) // note the missing reference
{
std::swap(ptr, source.ptr);
return *this;
}
由于移动赋值运算符应该对 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);
}
但是编译器警告我它试图复制引用的对象但失败了,因为复制构造函数被删除了。我不明白为什么在 unique_ptr
的示例中它是正确的。当我们调用函数时,对象应该被 copied,所以 move语义化。
你不能解释一下吗?
调用移动构造函数从相同类型的 rvalue 构造新对象。如果您尝试将 lvalue 传递给按值采用仅移动类型的函数,则它需要 copy 构造函数,您将得到一个错误。
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
本身不是一个可能的参数,因为解引用指针总是会产生一个左值。
表达式 *(new A)
不是右值。
关于什么表达式是右值的一般规则(不是 the actual rule,只是速记)是这样的:它要么是临时的,要么是您明确调用 std::move
的东西。而且 *(new A)
不是临时的。而且你没有在上面调用 move
。所以它不是右值。
尝试使用 A()
代替。