[英]GCC 3.42 and VC2008 treat std::transform differently, take a reference or a copy of the functor?
我在 Google 上搜索了這個與函子相關的主題,似乎人們通常會說標准庫默認將函子作為副本。 已經找到了許多示例,這對於std::for_each
是正確的。 GCC 和 VC2008 編譯器產生了相同的結果:都復制了仿函數。
但是對於std::transform
我發現下面的測試代碼有所不同:
#include <iostream>
#include <vector>
using namespace std;
#define MSG(msg) cout << msg << endl;
struct MyFunctor{
MyFunctor()
{
MSG("MyFunctor constructor");
}
MyFunctor(const MyFunctor& myf)
{
MSG("MyFunctor copy constructor");
}
~MyFunctor()
{
MSG("MyFunctor destructor");
}
int operator()(int i)
{
i = -(i+1);
return i;
}
};
int main()
{
vector<int> myvec;
myvec.push_back(1);
myvec.push_back(1);
myvec.push_back(1);
myvec.push_back(1);
std::transform(myvec.begin(),myvec.end(),myvec.begin(),MyFunctor());
system("pause");
}
/*
gcc result:
MyFunctor constructor
MyFunctor destructor
vc2008 result:
MyFunctor constructor
MyFunctor copy constructor
MyFunctor copy constructor
MyFunctor destructor
MyFunctor destructor
MyFunctor destructor
*/
結果似乎表明 GCC 將MyFunctor
作為參考,而 vc2008 將其作為副本(就像它們都對待for_each
一樣)。
為什么 GCC 和 vc2008 在這件事上表現不同,哪一個應該是正確的做法?
結果似乎表明 GCC 將 MyFunctor 作為參考,而 vc2008 將其作為副本
您無法從結果中推斷出這一點。 我們有“復制省略”之類的東西。 C++ 標准明確允許編譯器在某些情況下優化不必要的副本。 libstdc++ 的轉換也完全有可能按值獲取函子(我沒有檢查過),並且 G++ 編譯器只是擺脫了不必要的副本。 當編譯器執行復制省略時,它會將兩個或多個對象組合成一個對象。 在您的情況下,您創建了一個臨時的 MyFunctor object。 然后,還有另一個 MyFunction object(函數的參數)。 允許 GCC 使這個臨時變量與命名的 function 參數所指的 object 相同。 事實上,每當一個新的 object 用相同類型的臨時對象初始化時,編譯器就可以忽略這個副本並將兩個對象組合成一個對象。
對此進行測試:將臨時 MyFunctor object 替換為您之前聲明的變量名:
MyFunctor mf;
...
std::transform(...,mf);
在這種情況下,不允許復制省略,因為 mf 不是右值而是左值。 您可以期望看到您的復制構造函數打印一些東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.