以下哪个是 std::move 的正确用法

Osc*_*car 2 c++ move rvalue

我正在尝试更改我的代码以使用 std::move 按值获取向量,而不是按引用传递它,因为我已经收集到这样会更有效。不过,我已经看到了不同的方法,一种是让构造函数按值传递并在构造函数中使用 std::move,另一种方法是用 std::move 初始化类并让构造函数采用右值(我做对了吗?)。下面的一些例子:

方法一:

构造函数:

StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>> Inner_) :Inner(std::move(Inner_))
{
}
Run Code Online (Sandbox Code Playgroud)

在主要:

vector<Wrapper<StatisticsMC>> gathererArray{ meanGatherer, absQuantileGatherer, relVaRGatherer, relESGatherer };
StatisticsCompiler gathererCombiner(gathererArray);
Run Code Online (Sandbox Code Playgroud)

方法二。

构造函数:

StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>>&& Inner_) :Inner(Inner_)
{
}
Run Code Online (Sandbox Code Playgroud)

主要的:

vector<Wrapper<StatisticsMC>> gathererArray{ meanGatherer, absQuantileGatherer, relVaRGatherer, relESGatherer };
StatisticsCompiler gathererCombiner(std::move(gathererArray));
Run Code Online (Sandbox Code Playgroud)

这里发生的事情之间是否有区别,或者是同一件事,第一种方法在 main 中“看起来”更好,但第二种方法是我直观地理解它以学习右值的方式。如果在性能方面它们完全相同,那么标准做法是什么?

eer*_*ika 7

StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>> Inner_) :Inner(std::move(Inner_))
Run Code Online (Sandbox Code Playgroud)

此构造函数按值接受参数。参数可以从左值参数复制构造,也可以从右值移动构造。这种在从左值复制和从右值移动之间进行选择的能力,加上简单性,是推荐这种方法的原因。

该成员总是从复制或移动的参数中移动。

StatisticsCompiler gathererCombiner(gathererArray);
Run Code Online (Sandbox Code Playgroud)

你传递了一个左值;因此参数被复制。您可以通过传递右值来使用移动构造函数:

StatisticsCompiler gathererCombiner(std::move(gathererArray));
Run Code Online (Sandbox Code Playgroud)

或者你甚至可以使用纯右值:

 StatisticsCompiler gathererCombiner({
    meanGatherer,
    absQuantileGatherer,
    relVaRGatherer,
    relESGatherer,
 });
Run Code Online (Sandbox Code Playgroud)
StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>>&& Inner_) :Inner(Inner_)
Run Code Online (Sandbox Code Playgroud)

此构造函数仅接受右值参数。这不像第一个建议那样灵活,第一个建议也可以接受左值。

这种方法总是将参数复制到成员中。您可能想要移动:

Inner(std::move(Inner_))
Run Code Online (Sandbox Code Playgroud)

结论:当您想存储作为参数给出的对象时,按值传递(第一个示例)是很好的默认选择。如果您之后不需要传递的参数,那么您可以选择从它移开。