c++ - 按值返回的函数的值类别是否总是 xvalue?

标签 c++ c++11 c++14 move xvalue

根据我的理解,下面的代码应该调用 Test 类的 move 构造函数,因为这个函数按值返回,这意味着表达式 GetTestObj() 应该是右值,xvalues 是隐式的 move 但为什么这段代码调用复制构造函数?

class Test
{
  public:
         Test()
         {
         }
         Test(const Test& arg)
         {
            std::cout<<"Copy Constructor Called..."<<std::endl;
         }
         Test(Test&& arg)
         {
            std::cout<<"Move Constructor Called..."<<std::endl;
         }
};

Test  GetMyTestObj()
{
      Test *ptr = new Test();
      return *ptr;
}
Test dummy = GetMyTestObj(); //Copy Constructor Called...

最佳答案

在您的代码中,实际上有一个拷贝从 *ptr 到返回值,还有一个从 GetMyTestObj()dummy。但是,编译器 elides move ,所以你不会看到它被跟踪。如果您将 -fno-elide-constructors 传递给 GCC 或 Clang,那么您应该会看到拷贝和 move (demo)。

如果要将返回值构造为move,需要使用std::move:

Test GetMyTestObj()
{
      Test *ptr = new Test();
      return std::move(*ptr);
}

但是,在这种情况下确实不需要动态分配;它效率低下并且会在您的实现中泄漏内存。你应该只使用一个自动变量:

Test GetMyTestObj()
{
    Test test;
    //I assume you're doing something else here
    return test;
}

使用上面的代码,编译器实际上可以省略这两个结构。

如果你在那个函数中什么都不做,你应该直接构造dummy:

Test dummy{};

关于c++ - 按值返回的函数的值类别是否总是 xvalue?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40460746/

相关文章:

c++ - 在 C++ 中将 char 数组添加到字符串

c++ - C/C++ extern "C"变量编译宏

c++ - 析构函数异常时返回值的破坏

c++ - 不能在从 std::vector 继承的类中使用 typedef 迭代器

c++ - 循环类依赖 : Forward declaration error vs. #include 错误 ("template argument invalid")

c++ - 这个丑陋的构造函数/工厂有 C++ 惯用语吗?

c++ - 声明对另一个类的模板化成员数组的模板化成员引用

c++ - 不使用 std::function 将捕获的 lambda 转换为函数指针

c++ - 用于检查枚举类是否可用的简单宏

c++ - Black Magic 使用 Initializer_list 和包扩展