欢迎光临
我们一直在努力

c RVO

RVO,是Return Value Optimization。这是在函数返回返回值的时候编译器所做出的优化,是C++11标准的一部分,C++11称之为copy elision。

在第一次编写的函数里面,编译器明确知道函数会返回哪一个局部对象,那么编译器会把存储这个局部对象的地址和存储返回值临时对象的地址进行复用,也就是说避免了从局部对象到临时对象的拷贝操作。这就是RVO。

实验

实验1

#include <iostream>struct Foo { Foo() { std::cout << “Foo()” << std::endl; } Foo(const Foo&) { std::cout << “Foo(const Foo&)” << std::endl; } // Foo(const Foo&&) { // std::cout << “Foo(const Foo&&)” << std::endl; // } Foo& operator = (const Foo&) { std::cout << “operator=(const Foo&)” << std::endl; return *this; } Foo& operator = (const Foo&&) { std::cout << “operator=(const Foo&&)” << std::endl; return *this; } ~Foo() { std::cout << “~Foo” << std::endl; }};Foo test1() { Foo f1; return f1;}Foo test2() { if (true) { Foo f1; return f1; } if (false) { Foo f1; return f1; }}int main() { Foo a = test1(); // const Foo& f = test2(); // Foo f = test2(); // std::cout << “hello edn” << std::endl; return 0;}

输出:

Foo() # f1 临时对象构造~Foo # 临时对象析构

实验二

让编译器在编译时期无法知道返回的临时对象

#include <iostream>struct Foo { Foo() { std::cout << “Foo()” << std::endl; } Foo(const Foo&) { std::cout << “Foo(const Foo&)” << std::endl; } Foo(const Foo&&) { std::cout << “Foo(const Foo&&)” << std::endl; } Foo& operator = (const Foo&) { std::cout << “operator=(const Foo&)” << std::endl; return *this; } Foo& operator = (const Foo&&) { std::cout << “operator=(const Foo&&)” << std::endl; return *this; } ~Foo() { std::cout << “~Foo” << std::endl; }};Foo test1() { Foo f1; return f1;}Foo test2() { if (true) { Foo f1; return f1; } if (false) { Foo f1; return f1; }}int main() { // test1(); // const Foo& f = test2(); Foo f = test2(); // std::cout << “hello edn” << std::endl; return 0;}

输出:

Foo() # f1临时对象构造Foo(const Foo&&) # f1 临时对象拷贝到返回值~Foo ~Foo 关闭RVO g++ class_inhert.cpp -std=c++14 -fno-elide-constructors

重复实验1:

Foo() # f1 临时对象构造Foo(const Foo&&) # f1 右值构造返回值临时对象~FooFoo(const Foo&&) # 通过返回值构造 a~Foo~Foo

重复实验二

Foo()Foo(const Foo&&)~FooFoo(const Foo&&)~Foo~Foo

新增实验3

test1 函数返回值改成右值, 返回类型是右值引用,没有临时对象的消耗,但是仍不可取,因为右值引用的对对象在使用前已经析构了。

#include <iostream>struct Foo { Foo() { std::cout << “Foo()” << std::endl; } Foo(const Foo&) { std::cout << 香港vps “Foo(const Foo&)” << std::endl; } // Foo(const Foo&&) { // std::cout << “Foo(const Foo&&)” << std::endl; // } Foo& operator = (const Foo&) { std::cout << “operator=(const Foo&)” << std::endl; return *this; } Foo& operator = (const Foo&&) { std::cout << “operator=(const Foo&&)” << std::endl; return *this; } ~Foo() { std::cout << “~Foo” << std::endl; } void like() { std::cout << “like” << std::endl; }};Foo&& test1() { Foo f1; return std::move(f1);}Foo test2() { if (true) { Foo f1; return f1; } if (false) { Foo f1; return f1; }}int main() { Foo&& a= test1(); // const Foo& f = test2(); // { // const Foo& f = test2(); // } a.like(); std::cout << “hello edn” << std::endl; return 0;}

输出:

Foo() # 临时对象构造~Foo # 临时对象析构,在使用前已经析构like # hello edn

?新增实验4:

返回值是右值,返回类型是类,??

#include <iostream>struct Foo { Foo() { std::cout << “Foo()” << std::endl; } Foo(const Foo&) { std::cout << “Foo(const Foo&)” << std::endl; } Foo(const Foo&&) { std::cout << “Foo(const Foo&&)” << std::endl; } Foo& operator = (const Foo&) { std::cout << “operator=(const Foo&)” << std::endl; return *this; } Foo& operator = (const Foo&&) { std::cout << “operator=(const Foo&&)” << std::endl; return *this; } ~Foo() { std::cout << “~Foo” << std::endl; } void like() { std::cout << “like” << std::endl; }};Foo test1() { Foo f1; return std::move(f1);}Foo test2() { if (true) { Foo f1; return f1; } if (false) { Foo f1; return f1; }}int main() { Foo&& a = test1(); // Foo a = test1(); // const Foo& f = test2(); // { // const Foo& f = test2(); // } // a.like(); std::cout << “hello edn” << std::endl; return 0;}

输出:

Foo() # f1 临时对象构造Foo(const Foo&&) # 返回值右值拷贝构造~Foohello edn~Foo

赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。