c++ - 从具有移动语义或返回值优化但不是复制构造函数的函数返回值

标签 c++ c++11

在保证不调用复制构造函数的 C++ 中,是否有一种从函数返回值的好方法?返回值优化或移动构造函数都可以。例如,使用以下代码

#include <iostream>

struct Foo {
private:
    // Disallow the copy and default constructor as well as the assignment
    // operator
    Foo();
    Foo(Foo const & foo);
    Foo & operator = (Foo const & foo);

public:                         
    // Store a little bit of data
    int data;                   
    Foo(int const & data_) : data(data_) { }

    // Write a move constructor 
    Foo(Foo && foo) {           
        std::cout << "Move constructor" << std::endl;
        data=foo.data;          
    }                           
};                              

// Write a function that creates and returns a Foo
Foo Bar() {                     
    Foo foo(3);                 
    return foo;                 
}                               

// See if we can mix things up  
Foo Baz(int x) {                
    Foo foo2(2);                
    Foo foo3(3);                
    return x>2 ? foo2 : foo3;   
}                               

int main() {                    
    // This is using the return value optimization (RVO)
    Foo foo1 = Bar();           
    std::cout << foo1.data << std::endl;

    // This should make the RVO fail 
    Foo foo2 = Baz(3);
    std::cout << foo2.data << std::endl;
}

编译错误

$ make
g++ -std=c++11 test01.cpp -o test01
test01.cpp: In function 'Foo Baz(int)':
test01.cpp:10:5: error: 'Foo::Foo(const Foo&)' is private
test01.cpp:35:25: error: within this context
make: *** [all] Error 1

因为复制构造函数是私有(private)的。现在,如果我们将 Baz 函数修改为

// See if we can mix things up
Foo Baz(int x) {
    Foo foo2(2);
    Foo foo3(3);
    return std::move(x>2 ? foo2 : foo3);
}

我们确实正确运行。然而,这似乎阻止了 RVO 的使用。如果我们必须保证不调用复制构造函数,是否有更好的方法来构造这些函数?

最佳答案

来自 C++ 标准:

[class.copy]/31: When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects. ... This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

  • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv- unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

因为 x > 2 ? foo2 : foo3 不是自动对象的名称,不允许复制省略。

关于c++ - 从具有移动语义或返回值优化但不是复制构造函数的函数返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20484153/

相关文章:

c++ - 我们应该如何实现对象类型的 move ?

c++ - 我应该使用 atomic 还是 volatile 作为指针?

c++ - 在 C++ 中使用 RAII 进行回调注册

c++ - 临时可修改适配器

c++11 - 为什么是 int* arr = {};合法的?

c++ - 可以使用对 shared_ptr 拥有的对象的引用吗?

c++ - 为满足条件的特定整数搜索 vector 的有效方法?

c++ - SELinux:重定位后无法恢复段保护:权限被拒绝

c++ - 模板和 ODR

C++ 在 vector 迭代器上调用模板化方法