C++ RVO/NRVO以及move语义的影响

C++返回值优化和具名返回值优化是编译器的优化,在大多数情况下能提高性能,但是却难以受程序员控制。C++11中加入了move语义的支持,由此对RVO和NRVO会造成一定影响。下面以一段代码来说明。

RVO和NRVO在分别在copy/move construct,copy/move assignment八种简单情况,测试条件是g++ 4.8.2和clang++ 3.4,默认优化。

#include <iostream>
#include <vector>
#include <string>

struct Test {
  Test()
  {
    //std::cout << "construct a Test object" << std::endl;
  }

  Test(const Test&)
  {
    std::cout << "copy construct  a Test object" << std::endl;
  }

  Test& operator=(const Test &t)
  {
    std::cout << "copy assignment a Test object" << std::endl;
    return *this;
  }

  Test(Test&& t)
  {
    std::cout << "move construct a Test object" << std::endl;
  }

  Test& operator=(Test &&t)
  {
    std::cout << "move assignment a Test object" << std::endl;
    return *this;
  }

  ~Test()
  {
    //std::cout << "destruct a Test object" << std::endl;
  }
};

Test getTest()
{
  // anonymous object 
  return Test();
}

Test getTestWithName()
{
  // named return value 
  Test temp;
  return temp;
}

int main()
{
  std::cout << "==== common case ====" << std::endl;
  Test o1;
  std::cout << "---- Test copy construct: " << std::endl;
  Test o2(o1);  // two ways for copy construct 
  Test o3 = o1;
  std::cout << "---- Test move construct: " << std::endl;
  Test o4(std::move(o3));
  std::cout << "---- Test assignment: " << std::endl;
  o2 = o1;
  std::cout << "---- Test move assignment: " << std::endl;
  Test o5; o5 = std::move(o4);

  std::cout << "\n==== test for rvo ===" << std::endl; 
  std::cout << "---- Test rvo for copy construct: " << std::endl;
  Test obj11(getTest());
  Test obj1 = getTest();
  std::cout << "---- Test rvo for move construct: " << std::endl;
  Test obj12(std::move(getTest()));
  std::cout << "---- Test rvo for assignment: " << std::endl;
  Test obj2; obj2 = getTest();
  std::cout << "---- Test rvo move assignment: " << std::endl;
  Test obj5; obj5 = std::move(getTest());

  std::cout << "\n==== test for nrvo ===" << std::endl; 
  std::cout << "---- Test nrvo for copy construct: " << std::endl;
  Test obj33(getTestWithName());
  Test obj3 = getTestWithName();
  std::cout << "---- Test nrvo for move construct: " << std::endl;
  Test obj34(std::move(getTestWithName()));
  std::cout << "---- Test nrvo for assignment: " << std::endl;
  Test obj4; obj4 = getTestWithName();
  std::cout << "---- Test nrvo move assignment: " << std::endl;
  Test obj6; obj6 = std::move(getTestWithName());

  return 0;
}

测试结果:

==== common case ====
---- Test copy construct: 
copy construct  a Test object
copy construct  a Test object
---- Test move construct: 
move construct a Test object
---- Test assignment: 
copy assignment a Test object
---- Test move assignment: 
move assignment a Test object

==== test for rvo ===
---- Test rvo for copy construct: 
---- Test rvo for move construct: 
move construct a Test object
---- Test rvo for assignment: 
move assignment a Test object
---- Test rvo move assignment: 
move assignment a Test object

==== test for nrvo ===
---- Test nrvo for copy construct: 
---- Test nrvo for move construct: 
move construct a Test object
---- Test nrvo for assignment: 
move assignment a Test object
---- Test nrvo move assignment: 
move assignment a Test object

由此可得出几个简单结论:
1.copy construct本身在RVO和NRVO两种情况下被优化了,如果再加上move反而画蛇添足。
2.加入了move assignment后,默认是调用move assignment而不是copy assignment,可以将move assignment注释后测试。
3.对于RVO和NRVO来说,construction的情况编译器优化得比较好了,加入move语义主要是对于assignment有比较大影响

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值