这段代码
#include <tuple>
struct Foo
{
Foo(const int& value):value_(value){}
//Foo(const Foo&)=delete; // delete copy constructor
int value_;
};
int main()
{
std::tuple<Foo> tup(std::move(Foo(1)));
return 0;
}
工作正常,但如果删除Foo
复制构造函数,则会因以下编译错误而失败:使用已删除的函数Foo::Foo(const Foo&)
。
但是,既然我明确告诉对象可以移动,为什么std::tuple
构造函数使用Foo
复制构造函数而不是移动构造函数?如何强制std::tuple
构建移动Foo
实例而不是复制它?
答案 0 :(得分:3)
但是,因为我明确告诉对象可以移动,
不,您告诉编译器您想要要移动的对象。这不是一回事。
为什么
std::tuple
构造函数使用Foo
复制构造函数而不是其移动构造函数?
因为当您删除复制构造函数时,隐式移动构造函数不存在,因此无法使用它。
如何强制构造std :: tuple来移动Foo实例而不是复制它?
要么不删除复制构造函数,要么也定义移动构造函数:
struct Foo
{
Foo(const int& value):value_(value){}
Foo(const Foo&)=delete; // delete copy constructor
Foo(Foo&&)=default;
int value_;
};
N.B。这里的std::move
完全没用:
std::tuple<Foo> tup(std::move(Foo(1)));
所有std::move
确实将其参数强制转换为右值,但临时Foo(1)
已经是右值,因此您正在向右值投射右值:无用。此外,如果没有std::move
,编译器可以copy elision并优化实际移动,但是当您使用std::move
时,它无法执行此操作并且您创建代码慢不快!
最佳代码是最简单的版本:
std::tuple<Foo> tup(Foo(1));
甚至更简单:
std::tuple<Foo> tup(1);