概念上沒有需要的副本。現代編譯器能否在這種情況下刪除所有副本?
是的,如果函數是內聯的,則是可能的。但是,我想考慮下面的代碼示例而不是您自己的代碼示例,因爲std::string
是一個充滿晦澀優化的野獸。
所以我們來考慮一個int
的例子。來電者有{1, 2, 3}
,並且想從中創建一個std::vector<int>
,其中包含{2, 4, 6}
。 (這大致上是在呼叫者處具有文字"text"
並且想要構建包含"TEXT"
的std::string
的模擬。)
代碼:
#include <cstdio>
#include <vector>
using namespace std;
vector<int> mult(vector<int> v) {
for (int& e : v)
e *= 2;
return v;
}
int main() {
vector<int> v(mult({1, 2, 3}));
for (int i : v)
printf("%d\n", i);
}
如果我用gcc 4.7.2作爲編譯:g++ -O3 -fwhole-program -Wall -Wextra -std=c++11 -S file.cpp
,我得到了大會只有一個std::vector<int>
析構函數調用。 該矢量是在原地創建的。生成的程序集儘可能好。
如果我編譯完全相同的代碼,但省略了-fwhole-program
旗,mult()
功能沒有得到內聯,我得到兩次調用的std::vector<int>
析構函數。生成的組件也比前一種情況差得多。
鏘不知道-fwhole-program
標誌,所以我增加了static
關鍵字mult()
:
static vector<int> mult(vector<int> v) { ...
,然後它也創造就地載體。
From James Kanze's answer:
與值參數,該參數是被調用者,誰 看不到(一般),該參數將返回構造,所以 不能建立在正確的地點。
我做了什麼上面(內聯mult()
)使我們能夠調用方可以看到該參數將返回和效果,結果就地構建。
來源
2014-02-20 16:29:25
Ali
在這種情況下,編譯器不允許在返回中刪除副本,並且AFAIK在這裏也沒有隱式的'移動'。 – Simple
@Simple:如果類型是可移動的,返回值將被移動(如'字符串在這裏)。 –
與您的問題無關,但您的代碼具有未定義的行爲(假設它編譯了,可能不會)。 'std :: transform'會用'char'調用'std :: toupper',如果簡單的'char'被簽名(通常是這種情況),會導致未定義的行爲。 –