c ++如何选择移动和复制构造

问题描述

我正在自己制定“任何”课程。如以下代码所示,我有两个问题。

#include <assert.h>
#include <iostream>
#include <typeinfo>

class Test{};

class Any {
 public:
  template<typename DataType>
  explicit Any(DataType&& in) {
    Test t;
    std::cout
        << typeid(t).name() << "  "
        << typeid(in).name() << "  "
        << typeid(test()).name();
    std::cout << " move";
  }
  template<typename DataType>
  explicit Any(const DataType& in) {
    Test t;
    std::cout
        << typeid(t).name() << "  "
        << typeid(in).name() << "  "
        << typeid(test()).name();
    std::cout << " copy";
  }
};

int main()
{
  Test t;
  Any a(t);
}

编译命令是

g++ main.cpp -std=c++11

输出

4Test  4Test  F4TestvE move
  1. 为什么 c++ 选择移动构造而不是复制构造? “t”是 Test 的一个实例,它不是右值。
  2. 为什么 typeid(in) 和 typeid(test()) 不一样?它们都是右值。

非常感谢。

解决方法

  1. 为什么 c++ 选择移动构造而不是复制构造? “t”是 Test 的一个实例,它不是右值。

第一个构造函数重载采用 forwarding reference 并且可以接受左值和右值。 (因此它不是移动构造函数。)对于 Any a(t); 它是完全匹配,而对于第二个重载 t 需要转换为 const

  1. 为什么 typeid(in) 和 typeid(Test()) 不一样?它们都是右值。

Test() 是一个函数类型,它返回 Test 并且不带任何东西,因此 typeid(Test()) 给出了不同的结果。

,

您的移动变体被调用的原因是它的签名实际上并不需要传递右值引用。

如果 U = T const&,那么 U&& 将是 T const&,而不是 T&&。在您的情况下,DataType 绑定到 Test&,而不是像您预期的那样绑定到 Test。因此 && 会折叠并且什么也不做。如果您添加将通过的 static_assert(std::is_same_v<DataType,Test&>);,您可以看到这一点。
如果您用固定类型替换模板,即 Test&& 而不是 DataType&&,您的函数将被调用。

查看 reference,参考折叠部分。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...