即使在禁用 RVO 时定义了移动构造函数,也会发生对象复制

object copy happens even with move constructor defined when RVO disabled

我碰巧发现了一个场景,我正在 return 通过值从函数中获取一个对象。

在 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++11gcc 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被禁用并且对象定义为移动操作时,应该调用移动构造函数。

为什么这里没有搬迁施工?我错过了什么吗?

谢谢。

It seems that in the line myObject c = GetObject_Complex(1,0), copy operation is happening.

有点,但不完全是。更准确地说,复制操作发生在 GetObject_Complex 内,当 三元条件运算符的结果被复制到临时 return 值。

Why move construction is not happening here?

没有移动构造函数,因为编译器从函数调用的结果中删除了移动作为优化。