1

使用 RVO,我们可以从函数返回局部变量,而不会产生复制成本。这在返回变量的子对象时也有效吗?

从其他答案中,我收集到当完整对象的大小大于要返回的对象时,它不会,因为它不适合为返回值保留的空间。但是如果整个对象是“空的”,即大小与子对象相同,那又如何呢?


我问这个问题的理由:

假设我有一个简单的对象

struct Data {
    std::string s;
    int i;
};

和一个包装类,它只是作为数据的更智能视图:

class WrapperRef {
    Data& d;
public:
    WrapperRef(Data& data) : d(data) {}
    // some dummy functions operating on the data
    char& foo() { return d.s[d.i]; }
};

这被一些返回Data以简化实现的函数在内部使用,但接口没有反映这一点(即函数不返回包装器本身)。所以我可能有一个功能:

Data makeTheData(...) {
    Data localData;
    WrapperRef wrapper{localData};

    // Manipulate the data using the wrapper
    // ...

    return localData;
}

由于这个用例对于我的包装器来说很常见,我想用一个封装它的类来替换它。makeTheData即,我将用包含Data子对象和包装器功能的单个本地对象替换前两行。

class ContainingWrapper {
    Data d;
public:
    ContainingWrapper() = default;
    // some dummy functions
    char& foo() { return d.s[d.i]; }

    // Convert to actual Data object. Maybe use other means instead such as a getter method?
    operator Data&() { return d; }
};

Data makeTheData(...) {
    ContainingWrapper wrapper;

    // Manipulate the data using the wrapper
    // ...

    return wrapper;
}

这将有助于实现包装器的常见用例。该ContainingWrapper对象与对象具有相同的大小Data,因此 RVO 在技术上应该是可行的。

能否在不损失 RVO 性能(至关重要)的情况下实现此功能(使用成员或基础子对象,或者可能使用不同的方法)?as if规则是否适用并允许优化器将第二个实现makeTheData转换为第一个实现,从而使 RVO 成为可能?

4

0 回答 0