C++ 以下哪项是std::move的正确用法

C++ 以下哪项是std::move的正确用法,c++,move,rvalue,C++,Move,Rvalue,我正试图改变我的代码,使用std::move按值获取向量,而不是通过引用传递,因为我已经收集了更有效的方法。不过,我看到了不同的方法,一种是让构造函数按值传递并在构造函数中使用std::move,另一种是用std::move初始化类并让构造函数获取右值(我做对了吗?)。以下是一些例子: 方法1: 建造商: StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>> Inner_) :I

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

方法1:

建造商:

StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>> Inner_) :Inner(std::move(Inner_))
{
}
StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>>&& Inner_) :Inner(Inner_)
{
}
StatisticsCompiler::StatisticsCompiler(std::vector内部):Inner(std::move(内部))
{
}
大体上:

vector<Wrapper<StatisticsMC>> gathererArray{ meanGatherer, absQuantileGatherer, relVaRGatherer, relESGatherer };
StatisticsCompiler gathererCombiner(gathererArray);
vector gathereray{meanGatherer,absQuantileGatherer,relVaRGatherer,relsgater};
统计编译器GatherCombiner(GatherArray);
方法2

建造商:

StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>> Inner_) :Inner(std::move(Inner_))
{
}
StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>>&& Inner_) :Inner(Inner_)
{
}
StatisticsCompiler::StatisticsCompiler(std::vector&&Inner):Inner(Inner)
{
}
主要内容:

vector gathereray{meanGatherer,absQuantileGatherer,relVaRGatherer,relsgater};
统计编译器gathererCombiner(std::move(gathererArray));
这里发生的事情有区别吗?或者是同一件事,第一种方法大体上“看起来”更好,但第二种方法是我通过学习右值直观地理解它的工作方式。如果在性能方面它们完全相同,那么标准做法是什么

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

StatisticsCompiler gathererCombiner(std::move(gathererArray));
或者您甚至可以使用prvalue:

 StatisticsCompiler gathererCombiner({
    meanGatherer,
    absQuantileGatherer,
    relVaRGatherer,
    relESGatherer,
 });



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

我更喜欢第二个版本,即显式版本。我喜欢看到显式的构造函数/函数签名来理解发生了什么。这使我们更容易对代码进行推理。@jvd但它明确说明了什么?好的,只有在接收对象拥有资源的唯一所有权的情况下才应该提供移动重载。没有证据表明情况如此,因为OP只提到了性能问题。因此,仅仅提供这种服务,并没有明显的原因,只会妨碍用户。编辑:而且,正如HTNW指出的,它甚至不起作用,因为您无论如何都不会在实现内部移动!这回答了你的问题吗?请注意,第二个副本。“显式”右值引用令人困惑,因为
std::vector&&Inner
意味着
Inner
绑定到右值,但是
Inner
作为一个表达式仍然是一个左值,除非您再次
std::move
它,否则将从中复制。@Oscar Yes。通过右值引用获取参数和通过值获取参数之间的唯一区别是灵活性(如回答中所述),后者更灵活,因此通常更好。明确性其实并不那么重要。“按值传递然后移入”实现意味着一个重载,并且对用户可以/必须对其传递的内容执行的操作没有限制。不幸的是,这似乎泄露了实现细节(如果可能的话,可以选择移动),但这就是语言的现状,也必须如此。这是使99%的场景足够好地工作的最佳方法(R)(TM)。必须为每个构造函数/方法/参数添加移动重载只会导致成员函数重载的组合爆炸,如果不能证明额外的副本是一个现实问题,那么这就是浪费时间。值得注意的是,按值获取的建议只适用于从它移动到内部时。在几乎所有其他情况下,最好使用某种引用。
 StatisticsCompiler gathererCombiner({
    meanGatherer,
    absQuantileGatherer,
    relVaRGatherer,
    relESGatherer,
 });
StatisticsCompiler::StatisticsCompiler(std::vector<Wrapper<StatisticsMC>>&& Inner_) :Inner(Inner_)
Inner(std::move(Inner_))