删除元组成员的复制构造函数会导致错误

时间:2015-09-28 15:30:05

标签: c++ c++11 copy-constructor move-constructor stdtuple

这段代码

#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实例而不是复制它?

1 个答案:

答案 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);