0

这段代码

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

4

1 回答 1

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_;
};

注意std::move这里完全没用:

std::tuple<Foo> tup(std::move(Foo(1)));

所做std::move的只是将其参数转换为右值,但临时Foo(1)值已经是右值,因此您将右值转换为右值:无用。此外,没有std::move编译器可以进行复制省略并优化实际移动,但是当您使用std::move它时无法做到这一点,并且您会使代码变慢而不是变快!

最佳代码是最简单的版本:

std::tuple<Foo> tup(Foo(1));

或者更简单:

std::tuple<Foo> tup(1);
于 2015-09-28T15:48:17.813 回答