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

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结构没有定义任何特殊的成员函数(复制构造函数,析构函数等),这意味着会自动生成一个默认的 move 赋值运算符和一个默认的 move 拷贝构造函数,它们将 move 该结构的每个数据成员。因此Test是可 move 的类型,并且由于vector<size_t>是可 move 的数据成员而从中受益。

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

    vecOfTest.push_back(test);
}

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

唯一不需要 move 的情况是 move 会干扰省略。例如,在返回Test的函数中,这是:
Test test;
return std::move(test);

会 move ,但最好不要 move 。最好:
return test;

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

不是为了省事,所以永远不会发生隐性举动。

关于c++ - 在向 vector 添加自定义对象时如何启用 move 语义?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55965412/

10-16 04:39