C++关于返回值优化的问题

标签 c++

这个网站上有很多关于返回值优化的问题(我想这是一个相当令人困惑的话题),但我似乎找不到一个可以回答我的特定问题的问题。如果我的代码如下所示:

returnType function() { stuff....}

void someOtherFunction()
{
    returnType var = function();
    more stuff...
}

我被告知编译器可能决定在 someOtherFunction() 中不使用 returnType 的两个实例。从逻辑上讲,我希望 function() 会生成一个 returnType 类型的对象,而 someOtherFunction() 会通过复制构造函数接收该值(重载与否)转换为临时值。然后,我希望临时值通过赋值(可以重载,理论上可以具有任何功能!)复制到 var 中,该值之前已通过默认构造函数初始化。

我在这里看到了一个潜在的问题。如果 someOtherFunction() 中没有 returnType 的临时拷贝会怎样? var 是否必须通过复制构造函数直接用 function() 的返回值填充?如果是这样,赋值运算符不会被调用吗?如果是这样,并且如果赋值运算符被重载,那不会改变程序的功能吗?如果是这样,这是否意味着程序员有责任确保 = 始终与复制构造函数执行相同的操作?而且我讨厌运行这么长的一系列问题,但是如果是这样,为什么 C++ 允许您定义复制构造函数来执行赋值以外的操作?

最佳答案

I would then expect that temporary value to be copied via assignment (which could be overloaded and in theory could have any kind of functionality!) into var, which would have previously been initialized via the default constructor.

嗯,对于初学者来说,这是完全错误的。

int x = 0;
int x(0);

这两行是同一个东西——构造函数调用。有一些区别——我相信第一个不能调用显式构造函数——但它们是相同的函数调用。没有默认构造,也没有赋值运算符调用。它们都是直接构造。

基本上,标准说“如果您在复制构造函数中复制对象之外的其他操作,这是您自己的愚蠢错误,当优化器消除调用时,您的程序没有表现出预期的行为,我笑了”。当然,这些是我自己的意译,但标准对允许优化器消除拷贝非常明确。在 C++0x 中,这也适用于移动。

你上面的代码片段是真的

returnType function() { stuff....}

void someOtherFunction()
{
    returnType var(function());
    more stuff...
}

这不是优化的版本,它就是这样。 从不调用赋值运算符。使用 NRVO,它看起来像

void function(void* mem) { // construct return value into mem
    new (mem) returnType;
    // Do shiz with returnType;
}
void someOtherFunction() {
    // This doesn't respect some other things like alignment
    // but it's the basic idea
    char someMemory[sizeof(returnType)];
    function(someMemory);
    // more stuff here
}

当然,即使在异常情况下,编译器也必须处理破坏对象,并确保所有别名的类型和对齐方式正确,以及其他一些我在我的文章中没有处理的事情示例,但希望您能了解一般要点。

关于C++关于返回值优化的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6879482/

相关文章:

C++检测传递给函数的const int

c++ - 如何覆盖 C++ 中的函数

c# - 尝试使用 swig 将 C++ 库与 C# 链接 - 不会让我将对 resulging dll 的引用添加到 C# 项目

c++ - 使用条件内循环的 OpenMP 调度是否仍然有效?

使用指针的动态 LinkedList 的 push() 和 pop() 方法的 C++ 问题

c++ - 在 C++ 中将指向对象的指针转换为 void *

c++ - TrySubmitThreadpoolCallback 未声明的标识符

c++ - 有什么简单的方法可以检查两个数字是否有不同的符号?

c++ - 如何根据对象的某些字段在 C++ 中的对象 vector 中获取最小或最大元素?

c++ - 即使使用 lib 文件也无法修复未解析的外部符号 _AES_encrypt