【问题标题】:Under what scenarios are the move constructors invoked for constructor arguments?在什么情况下为构造函数参数调用移动构造函数?
【发布时间】:2019-04-12 22:40:54
【问题描述】:

我试图了解何时调用构造函数参数的移动构造函数。

我将使用下面实际项目中的一些示例和场景来更好地说明我的问题。

解释一下为什么我会看到这些场景的结果会非常有帮助!

//The following code is common to all examples
//This code is the place the object creation begins
std::unique_ptr<AI::Pathfinding::cDirectedWeightedGraph> graph = std::make_unique<AI::Pathfinding::cDirectedWeightedGraph>(std::move(connections));

x---------------------------------------------- --------------x

场景 1:

//Here is the actual constructor for the class
cDirectedWeightedGraph(std::vector<cConnection> i_connections) : m_connections(i_connections) {}

结果: 调用 std::vector 类的移动构造函数。

x---------------------------------------------- --------------x

场景 2:

//Here is the actual constructor for the class
cDirectedWeightedGraph(std::vector<cConnection>&& i_connections) : m_connections(i_connections) {}

结果: 未调用 std::vector 类的移动构造函数。

x---------------------------------------------- --------------x

场景 3:

//Here is the actual constructor for the class
cDirectedWeightedGraph(std::vector<cConnection>&& i_connections) : m_connections(std::move(i_connections)) {}

结果: 调用 std::vector 类的移动构造函数。

x---------------------------------------------- --------------x

场景 4:

//Here is the actual constructor for the class
cDirectedWeightedGraph(std::vector<cConnection> i_connections) : m_connections(std::move(i_connections)) {}

结果: 调用 std::vector 类的移动构造函数。

x---------------------------------------------- --------------x

观察/跟进问题:

  1. 参数是否被声明为右值引用似乎根本不重要。

  2. 除了为您的类编写移动构造函数或移动赋值运算符之外,您是否需要在构造函数中使用右值引用?

  3. 我假设在调用构造函数的位置,如果不传递右值引用,就无法调用移动构造函数(无论哪种方式,这似乎都是不好的做法,我只是好奇)。我正在使用 std::move() 生成右值引用。

【问题讨论】:

    标签: c++11 optimization constructor move-constructor


    【解决方案1】:

    我们知道如果我们调用std::move,那么移动构造函数会被调用,所以3和4是预期的。

    对于 1,我会首先检查您的编译器设置,调试不会生成移动构造函数。如果您有一个使用i_connections 的语句,您将看不到移动构造函数。 clang-tidy 甚至有一个规则可以检测这些情况并建议将 1 替换为 4。

    对于场景 2,编译器决定不生成优化代码。可能有一种启发式方法与案例 1 的工作方式略有不同。编译器不必优化代码,即使参数是 &amp;&amp;,因为它被命名,因此需要调用 @ 987654324@ 在所有情况下都将被移动。

    所以对于场景 1 和 2,它取决于编译器和标志。

    最后还是建议尽量使用4,因为编译器可以根据需要优化动作,接口也可以根据需要兼容副本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2020-11-22
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      相关资源
      最近更新 更多