簡體   English   中英

編譯器優化

[英]compiler optimization

所以我有一個問題要問你。 :)您能告訴我以下代碼應產生的輸出嗎?

#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;
}

我的第一反應是:

  1. tor
  2. 復制ctor
  3. 移動控制器
  4. dtor
  5. dtor
  6. dtor

這是真的,但前提是必須關閉編譯器優化 打開優化后,輸出將完全不同。 啟用優化后,輸出為:

  1. tor
  2. 復制ctor
  3. dtor
  4. dtor

通過編譯器優化,測試變量是返回變量。

我的問題是,什么條件會導致這種情況無法得到優化?

我一直被教導,返回一個struct / class會導致額外的復制構造函數,可以通過將其作為引用傳遞來更好地進行優化,但是編譯器正在為我做這件事。 那么返回結構仍然被認為是不好的形式嗎?

這被稱為“ 復制清除” ,是一種特殊的處理方式,而不是復制/移動。

只要有可能復制/移動(即方法已聲明且可訪問),標准就特別允許優化。

在這種情況下,通常將編譯器中的實現稱為“ 返回值優化” 有兩種變體:

  • RVO :返回臨時值時( return "aa" + someString;
  • NRVO :當您返回具有名稱的對象時,N為“命名”

兩者都由主要的編譯器實現,但是后者可能僅在較高的優化級別上才能啟動,因為它更難檢測。

因此,回答您有關返回結構的問題: 我會推薦它 考慮:

// Bad
Foo foo;
bar(foo);

-- foo can be modified here


// Good
Foo const foo = bar();

后者不僅更清晰,而且還可以執行const

兩個輸出都是允許的。 C ++ 03語言標准在第12.8 / 15節中指出:

當滿足某些條件時,即使該對象的副本構造函數和/或析構函數具有副作用,也允許實現忽略類對象的副本構造。 在這種情況下,實現將被忽略的復制操作的源和目標視為引用同一對象的兩種不同方式,並且該對象的銷毀發生在兩個對象本來可以銷毀而沒有銷毀的較晚時間發生優化。 111)在以下情況下(可以結合使用以消除多份副本),可以簡化此復制操作:

  • 在具有類返回類型的函數的return語句中,當表達式是具有與函數返回類型相同的cv-unqualified類型的非易失性自動對象的名稱時,可以通過構造自動對象來省略復制操作直接進入函數的返回值
  • 當將尚未綁定到引用(12.2)的臨時類對象復制到具有相同cv-unqualtype類型的類對象時,可以通過將臨時對象直接構造到省略副本的目標中來省略復制操作

該代碼將產生的輸出是不可預測的,因為語言規范明確允許對類對象的“不必要的”臨時副本進行可選的消除(刪除),即使它們的副本構造函數有副作用。

是否會發生這種情況可能取決於包括編譯器優化設置在內的多種因素。

在我看來,將上述復制省略稱為“優化”並不完全正確(盡管在此使用此術語的願望是完全可以理解的,並且已廣泛用於此目的)。 我會說,術語“ 優化”應保留給編譯器偏離 抽象C ++機器的行為,同時保留程序的可觀察行為的情況。 換句話說,真正的優化意味着違反了語言規范的抽象要求。 由於在這種情況下沒有沖突(標准明確允許復制省略),因此沒有真正的“優化”。 我們在這里觀察到的只是C ++語言在其抽象級別的工作方式。 根本不需要涉及“優化”的概念。

即使按值返回,編譯器也可以使用Return Value Optimization來優化多余的副本。 http://en.wikipedia.org/wiki/Return_value_optimization

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM