gpt4 book ai didi

c++ - 如果未定义析构函数,为什么不进行返回值优化?

转载 作者:行者123 更新时间:2023-12-01 13:34:01 25 4
gpt4 key购买 nike

我希望从该测试程序的命名返回值优化(NRVO)中看到copy elision,但其输出是“地址不匹配!”。因此未发生NRVO。为什么是这样?

// test.cpp
// Compile using:
// g++ -Wall -std=c++17 -o test test.cpp
#include <string>
#include <iostream>

void *addr = NULL;

class A
{
public:
int i;
int j;

#if 0
~A() {}
#endif
};

A fn()
{
A fn_a;

addr = &fn_a;

return fn_a;
}

int main()
{
A a = fn();

if (addr == &a)
std::cout << "Addresses match!\n";
else
std::cout << "Addresses do not match!\n";
}
笔记:
  • 如果通过启用上面的#if定义了析构函数,则NRVO确实会发生(并且在某些其他情况下也会发生,例如定义虚拟方法或添加std::string成员)。
  • 尚未定义任何方法,因此A是POD结构,或者在最近的术语中是trivial class。我在上面的链接中没有看到对此的明确排除。
  • 添加编译器优化(到一个更复杂的示例中,不仅仅是减少为空程序!)没有任何区别。
  • 在第二个示例中查看assembly时,这甚至在我期望执行强制返回值优化(RVO)的情况下也会发生,因此上述NRVO不会通过使用fn_a中的fn()的地址来防止。 x86-64上的Clang,GCC,ICC和MSVC显示相同的行为,表明此行为是有意的,而不是特定编译器中的错误。
     class A
    {
    public:
    int i;
    int j;

    #if 0
    ~A() {}
    #endif
    };

    A fn()
    {
    return A();
    }

    int main()
    {
    // Where NRVO occurs the call to fn() is preceded on x86-64 by a move
    // to RDI, otherwise it is followed by a move from RAX.
    A a = fn();
    }
  • 最佳答案

    在返回prvalue的情况下允许这样做的语言规则(第二个示例)是:

    [class.temporary]

    When an object of class type X is passed to or returned from a function, if X has at least one eligible copy or move constructor ([special]), each such constructor is trivial, and the destructor of X is either trivial or deleted, implementations are permitted to create a temporary object to hold the function parameter or result object.The temporary object is constructed from the function argument or return value, respectively, and the function's parameter or return object is initialized as if by using the eligible trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object).[Note: This latitude is granted to allow objects of class type to be passed to or returned from functions in registers.— end note]



    Why does Return Value Optimization not happen [in some cases]?


    引用规则的注释中说明了该规则的动机。从本质上讲,RVO有时会比没有RVO效率低。

    If a destructor is defined by enabling the #if above, then the RVO does happen (and it also happens in some other cases such as defining a virtual method or adding a std::string member).


    在第二种情况下,这是由规则解释的,因为仅在析构函数很简单时才允许创建临时文件。
    在NRVO的情况下,我认为这取决于语言的实现。

    关于c++ - 如果未定义析构函数,为什么不进行返回值优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62985845/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com