私は NRVO を調査しており、さまざまなコンパイラでサポートされていますが、奇妙な動作に遭遇しました。これはかなり混乱しています。
サンプルコード:
#include <iostream>
using namespace std;
class X {
public:
X() {
cout << "Constructor 1" << endl;
}
};
X test() {
X a;
cout << &a << endl;
return a;
}
int main() {
X b = test();
cout << &b << endl;
return 0;
}
最適化レベル 2 (または 3) でコンパイルすると、出力は 2 つの異なるメモリ アドレスになります。ただし、私が理解している限り、関数コードは NRVO に対して有効です。
PS VS2010 でコンパイルされた同じコードと最適化レベル 2 は NRVO を使用します。
追加のコンストラクターを追加すると:
X(const X& h) {
cout << "Contsructor 2" << endl;
}
コンパイル後のアドレスは同じなので、NRVO が適用されていると思いますが、最適化レベルに関係なく発生します。
" X(const X& h) " は何らかの形で g++ に NRVO を使用することを暗示していますか? それともNRVOが全く適用されておらず何か違うのでしょうか?
前もって感謝します。
追加した。GCC バージョン:
$ g++ -v
Configured with: [....] -enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
gcc version 4.4.3
追加のテスト:X(const X& h)
コンストラクトと-fno-elide-constructors
g++ フラグを使用してコンパイルすると、「コピー」コンストラクターが呼び出され、予期される動作が行われます。それがなければ、NRVO は失敗します。異なるマシンでテスト: gcc 4.4.3 と gcc 4.3.* -> 同じ結果。
これまでのところ、__cxa_atexit (@yves の g++ のバージョンに存在) が何らかの形で異なる動作に影響を与えるかどうかはわかりません。(私が理解している限り、それとは関係ありませんが、それが呼び出し順序にもたらす変化を完全には理解していません)