我碰巧发现一个场景,我按值从函数返回一个对象。
在return语句处使用条件语句,RVO避免了。
这是代码:
#include <iostream>
#include <cstring>
class myObject {
public:
myObject() {
std::cout <<"Default Constructor called" << std::endl;
buffer = new char[1000];
this->sz = 1000;
}
myObject(std::size_t sz) {
buffer = new char[sz];
this->sz = sz;
}
myObject(const myObject& other) {
std::cout <<"Copy Constructor called" << std::endl;
buffer = new char[other.sz];
sz = other.sz;
std::memcpy(buffer,other.buffer,other.sz);
}
myObject(myObject&& other) noexcept {
std::cout <<"Move Constructor called" << std::endl;
buffer = other.buffer;
sz = other.sz;
other.buffer = NULL;
other.sz = 0;
}
myObject& operator=(myObject&& other) noexcept {
std::cout <<"Move Assignment called" << std::endl;
if(buffer != NULL) {
delete[] buffer;
sz = 0;
}
buffer = other.buffer;
sz = other.sz;
other.buffer = NULL;
other.sz = 0;
return *this;
}
myObject& operator=(const myObject& other) {
// self ref ignored
std::cout <<"Copy Assignment called" << std::endl;
if(buffer != NULL) {
delete[] buffer;
sz = 0;
}
buffer = new char[other.sz];
sz = other.sz;
std::memcpy(buffer,other.buffer,other.sz);
return *this;
}
~myObject() {
std::cout <<"~myObject()" << std::endl;
if(buffer != NULL) {
delete[] buffer;
buffer = NULL;
}
}
char * buffer = NULL;
std::size_t sz = 0;
};
myObject GetObject_Complex(int x,int y) {
myObject obj;
myObject d;
return x > y ? obj : d; // intentionaly made conditional to avoid Return value optimization
}
int main() {
myObject c = GetObject_Complex(1,0); // Why move constructor is not called here ?
std::cout << std::endl << std::endl;
myObject d = std::move(c);
std::cout << std::endl << std::endl;
myObject e;
std::cout << std::endl << std::endl;
e = std::move(d);
}
此处使用 g++ -g -std=c++11
gcc version 7.5.0
Default Constructor called
Default Constructor called
Copy Constructor called
~myObject()
~myObject()
Move Constructor called
Default Constructor called
Move Assignment called
~myObject()
~myObject()
~myObject()
似乎在myObject c = GetObject_Complex(1,0)
行中,正在发生复制操作。但根据我的理解,当RVO被禁用并且对象是通过 move 操作定义时,应该调用 move 构造函数。
为什么这里没有进行搬迁施工?我错过了什么吗?
谢谢。
最佳答案
It seems that in the line
myObject c = GetObject_Complex(1,0)
, copy operation is happening.
有点但不完全是。更准确地说,复制操作发生在 GetObject_Complex
内,当
三元条件运算符的结果被复制到临时返回值。
Why move construction is not happening here?
没有 move 构造函数,因为编译器从函数调用结果中省略了 move 作为优化。
关于c++ - 即使在 RVO 禁用时定义了 move 构造函数,也会发生对象复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64778919/