在向矢量添加自定义对象时如何启用移动语义? [英] How to enable move semantics when adding custom objects to a vector?

查看:88
本文介绍了在向矢量添加自定义对象时如何启用移动语义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码将包含大向量的对象传递到向量中.我希望它表现出色.我是否需要在对push_back的调用中将test强制转换为右值?我需要告诉编译器如何移动struct Test的实例吗?还是全部自动进行?

Below code passes objects that contain big vectors into a vector. I want this to be performant. Do I need to cast test to rvalue in the call to push_back? Do I need to tell compiler how to move instances of struct Test? Or does this all go automatically?

int main()
{
    struct Test
    {
        std::vector<size_t> vals;
        double sum;
    };
    std::vector<Test> vecOfTest;
    vecOfTest.reserve(100000);

    for (size_t i = 0; i < 100000; i++)
    {
        Test test{};
        test.vals.reserve(i);
        for (size_t j = 0; j < i; j++)
        {
            test.vals.push_back(j);
            test.sum += j;
        }
        vecOfTest.push_back(test);
    }


    return 0;
}

推荐答案

您的Test结构未定义任何特殊成员函数(副本构造函数,析构函数等),这意味着默认的移动分配操作符和默认的移动副本构造函数是自动生成的,它们将移动结构的每个数据成员.因此Test是可移动类型,并且由于vector<size_t>是可移动数据成员而从中受益.

Your Test struct does not define any special member functions (copy constructor, destructor, etc.) That means a default move assignment operator and a default move copy constructor are generated automatically, and they will move each data member of the struct. So Test is a movable type, and it benefits from that since vector<size_t> is a movable data member.

但是,不会自动执行移动,因为从对象移动会更改它.即使您认为这样:

However, moves are not performed automatically because moving from an object changes it. Even though you'd think that this:

    vecOfTest.push_back(test);
}

将执行隐式移动,因为作用域结束了,但不会.隐含的举动将使编译器和程序员都陷入困境.要求编译器证明使test无效是可以的.程序员将被要求不断研究是否需要显式移动,而其最终结果将是无论如何都只是进行显式移动.因此,由于这个原因,隐式移动不会发生(但请参阅下面的规则例外.)您需要自己执行此操作:

would do an implicit move because the scope ends, it will not. Implicit moves would put both the compiler and the programmer in a difficult situation. The compiler would be required to prove that invalidating test is OK. The programmer would be required to constantly investigate whether or not an explicit move is needed or not, and the end result of that would be to just do explicit moves anyway. So for that reason, implicit moves do not happen (but see below for the exception to the rule.) You need to do it yourself:

vecOfTest.push_back(std::move(test));

唯一不需要移动的情况是移动会干扰省略.例如,在返回Test的函数中,这是

The only case where you need to not move is when the move would interfere with elision. For example, in a function that returns a Test, this:

Test test;
return std::move(test);

会采取行动,但最好不要这样做.最好:

would move, but it's better not to. It's better to:

return test;

相反.这不是一个隐含的举动.这是一个省略.清除比移动快,而移动将阻止清除.但是,在无法进行省略的情况下,将执行隐式移动.这是我唯一知道发生隐式移动的位置的情况:作为省略的替代方法.您的原始代码:

instead. This is not an implicit move. It's an elision. Elision is faster than move, and doing a move would prevent elision. However, in cases where elision is not possible, then an implicit move is performed. This is the only case I know of where an implicit move will happen: as a substitute for elision. Your original code:

vecOfTest.push_back(test);

不是省略的情况,因此隐式移动永远不会发生.

is not a case for elision, and so an implicit move will never happen.

这篇关于在向矢量添加自定义对象时如何启用移动语义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆