簡體   English   中英

GCC 3.42 和 VC2008 對待 std::transform 的方式不同,獲取仿函數的引用還是副本?

[英]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.

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