作者littleshan (我要加入剑道社!)
看板C_and_CPP
标题 RVO vs inline
时间Tue Oct 20 14:04:17 2009
[修正]
RVO 不会消除 copy-assignment
[/修正]
1F:推 holymars:RVO是因为Compiler会把return value当成参数传进function 10/20 13:02
2F:→ holymars:里才会有的optimization吧..如果函式本身inline 10/20 13:03
3F:→ holymars:就不用把return value放在参数列上,自然也不会进行 10/20 13:03
4F:→ holymars:RVO啊.. 10/20 13:03
RVO 牵涉的不只是 implementation detail
它也会影响到语意
因为它是直接「消除」掉 copy-constructor
即使这个 copy-constructor 具有 side effect 也是一样会被省略
但 inline function 是不能影响语意的
compiler 不能因为 inline function 就自动省略该有的 constructor
除非说 copy-constructor 是 compiler 自己产生所以它知道内容
上面的例子比较不明显
我举 NRVO 来当例子
class Foo {
public:
Foo(const Foo& f)
{
puts("Foo::Foo()");
}
Foo() {}
Foo& operator=(const Foo& f)
{
puts("Foo::operator=()");
return *this;
}
};
inline Foo bar(const Foo& f)
{
Foo tmp = f; // copy constructor
return tmp;
}
int main()
{
Foo a;
Foo b = bar(a);
return 0;
}
如果依照你的说法
因为 inline function 的缘故
在宣告 b 的地方应该会展开成
Foo tmp = a;
Foo b = tmp;
因此会产生两次 copy-constructor 呼叫
但实际上只会有一次
因为 NRVO 允许 compiler 直接把 tmp 代换成 b 而节省一次 copy-constructor
「即使」在这个情况中因为 inline function 的缘故
使得 b 的位址没办法当作参数传进 function 当中
但 compiler 知道上述的程式码是「inline function 展开後」的结果
还是有办法让 NRVO 起作用的
另一方面
在一般情况下 compiler 不可能会把两次的 copy-constructor 缩减成一次
因为它不知道你在 copy-constructor 中写了什麽东西
所以无法保证
Foo tmp = a;
Foo b = tmp;
与
Foo b = a;
的结果是相同的
所以在这个 case 中
用 NRVO 来解释 compiler 消除掉 copy-constructor 的行为
才是最合理的
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.112.29.108
5F:→ Chikei:呃,inline的确不会有RVO,因为RVO消除的是obj A=func()中 10/21 01:46
6F:→ Chikei:obj A=(tmpObj B=func())的tmpObj B这个暂存物件,所以在 10/21 01:48
7F:→ Chikei:inline下不需要暂存returned value,自然也不用RVO,你所讲 10/21 01:49
8F:→ Chikei:修正,*消除的是拷贝returned value到tmpObj B这个动作 10/21 01:53
9F:→ Chikei:另外,copy assignment也不会被消除,根据ISO C++ 12.8.15 10/21 01:54
10F:→ Chikei:能省略的只有从tmpObj copy出来时的copy ctor跟func return 10/21 01:58
11F:→ Chikei:时,为了承接return值而用来产生tmpObj的copy ctor 10/21 01:59
12F:推 Chikei:上面那串讨论之所以=不会被invoke是因为obj A = B是直接呼 10/21 02:17
13F:→ Chikei:修正,*obj A = B等於obj A(B) (copy initialize)所以不会 10/21 02:18
14F:→ Chikei:动到operator= 10/21 02:19
15F:推 holymars:obj A = B; 和obj A(B)是不一样的 10/21 10:34
16F:→ holymars:前者是copy initialize,後者是direct initialize 10/21 10:35
17F:推 holymars:RVO也不是指省略掉tmpObj那件事 10/21 10:37
18F:→ holymars:12.8.15所允许的省略好像没什麽正式名称 就copy elison 10/21 10:38
19F:推 holymars:^^^^^^^修正一下 是12.8.15的第三个条件 10/21 10:53
※ 编辑: littleshan 来自: 140.112.29.108 (10/21 11:51)