编译器优化

Bab*_*ish 11 c++ optimization g++ visual-studio-2010

所以我有一个问题要问你.:)你能告诉我以下代码应该产生的输出吗?

#include <iostream>
struct Optimized
{
    Optimized() { std::cout << "ctor" << std::endl; }
    ~Optimized() { std::cout << "dtor" << std::endl; }
    Optimized(const Optimized& copy) { std::cout << "copy ctor" << std::endl; }
    Optimized(Optimized&& move) { std::cout << "move ctor" << std::endl; }
    const Optimized& operator=(const Optimized& rhs) { std::cout << "assignment operator" << std::endl; return *this; }
    Optimized& operator=(Optimized&& lhs) { std::cout << "move assignment operator" << std::endl; return *this; }
};

Optimized TestFunction()
{
    Optimized a;
    Optimized b = a;
    return b;
}

int main(int argc, char* argv[])
{
    Optimized test = TestFunction();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的第一反应是:

  1. 构造函数
  2. 复制ctor
  3. 移动ctor
  4. 析构函数
  5. 析构函数
  6. 析构函数

它是真的,但只有关闭编译器优化.当优化打开时,输出完全不同.打开优化后,输出为:

  1. 构造函数
  2. 复制ctor
  3. 析构函数
  4. 析构函数

通过编译器优化,测试变量是返回变量.

我的问题是,什么条件会导致不以这种方式优化?

我一直被告知,返回一个导致额外复制构造函数的结构/类可以通过作为引用传入进行优化,但编译器正在为我做这些.返回一个结构仍然被认为是不好的形式?

Mat*_* M. 14

这称为Copy Elision,是一种特殊处理,而不是复制/移动.

标准特别允许优化,只要可以复制/移动(即,声明和访问方法).

在这种情况下,编译器中的实现通常称为返回值优化.有两种变化:

  • RVO:当你返回一个临时(return "aa" + someString;)
  • 当您返回具有名称的对象时,NRVO:N表示命名

两者都是由主要编译器实现的,但后者可能只在更高的优化级别上启动,因为它更难以检测.

因此,回答关于返回结构的问题:我会推荐它.考虑:

// Bad
Foo foo;
bar(foo);

-- foo can be modified here


// Good
Foo const foo = bar();
Run Code Online (Sandbox Code Playgroud)

后者不仅更清晰,而且还允许const执法!