按值返回的函数的值类别总是xvalue
Is value category of function returning by value is always xvalue?
根据我的理解,下面的代码应该调用移动Test
类的构造函数,因为这个函数是按值返回的,这意味着表达式GetTestObj()
应该是右值,xvalue是隐式移动的,但是为什么这个代码调用复制构造函数?
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
。但是,编译器会忽略这个移动,所以您不会看到它被跟踪。如果您将-fno-elide-constructors
传递给GCC或Clang,那么您应该看到副本和移动(演示)。
如果你想构造一个移动的返回值,你需要使用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{};
value不在这里复制(由于复制省略,没有调用构造函数):
Test dummy = GetMyTestObj();
但这里:
return *ptr;
因为函数必须从左值引用生成右值对象。基本上,GetMyTestObj()
函数在这种情况下相当于:
Test *ptr = new Test();
Test returnValue(*ptr);
return returnValue;
这意味着表达式
GetTestObj()
应该是右值,xvalue被隐式移动
首先直接回答你的问题,GetTestObj()
是一个右值。
- 非引用返回类型的函数调用或重载操作符表达式,如
str.substr(1, 2)
、str1 + str2
或it++
;
关键是return *ptr;
需要复制/移动操作;ptr
是一个命名变量,为左值。*ptr
也是左值,它不能移动。
您可以使用std::move
显式地将其设置为可移动的xvalue:
return std::move(*ptr);
相关文章:
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 函数返回的 rvalue 引用(表达式)是 xvalue - 但没有标识?
- 为什么函数调用是xvalue(如果返回类型为rvalue)
- 将 std::string 的 xvalue 传递给函数,获取 std::string_view
- 如何定义一个仅绑定 xvalue 或 prvalue 而不绑定两者的函数
- 按值返回的函数的值类别总是xvalue