繁体   English   中英

为什么/以下代码中NRVO不加入g ++?

[英]Why does/ does not NRVO kick in g++ in the code below?

我一直在研究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 ++中存在)是否会以某种方式影响其他行为。 (据我所知,这与它无关,但是我不完全了解它给呼叫顺序带来的变化)

对我来说没关系,即使我没有启用优化,nrvo也适用:

$ mk nrvo
g++     nrvo.cpp   -o nrvo
$ ./nrvo
Constructor 1
0xbfe5a520
0xbfe5a520
$ g++ -v
Lecture des spécification à partir de /usr/lib/gcc/i386-redhat-linux/3.4.6/specs
Configuré avec: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
Modèle de thread: posix
version gcc 3.4.6 20060404 (Red Hat 3.4.6-8)

编辑 :尝试完全乐观地进行编译:

g++ -O3 nrvo.cpp   -o nrvo

希望能帮助到你。

是否可以使用RVO取决于ABI。 即使C ++标准允许,实现的ABI也可能不允许。 引用Itanium C ++ ABI

通常,C ++返回值的处理方式与C返回值相同。 这包括在寄存器中返回的类类型结果。 但是,如果返回值类型具有非平凡的副本构造函数或析构函数,则调用方将为临时对象分配空间,并将指向临时对象的指针作为隐式第一个参数传递到this参数和user参数之前。 被调用者将返回值构造到此临时对象中。

注意:尽管有名称,但Itanium C ++ ABI不仅用于Itanium。

并且引用的基C ABI指定如果结构具有特定大小,则将它们返回到寄存器中。 您的问题中的struct(类)也是如此。 具有非平凡的复制构造函数或析构函数使不可能在寄存器中返回该类,因此ABI必须指定不同的规则,并且在这些不同的规则下,RVO是可能的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM