簡體   English   中英

在gcc和MSVC中以不同方式調用函數參數的析構函數

[英]Destructor of a function argument being called differently in gcc and MSVC

在將一些C ++代碼從Microsoft Visual Studio移植到gcc時,我遇到了一個奇怪的錯誤,我最終歸結為:

#include <iostream>
using namespace std;

class Foo {
public:
    int data;
    Foo(int i) : data(i) 
    {
        cout << "Foo constructed with " << i << endl; 
    }
    Foo(const Foo& f) : data(f.data)
    {
        cout << "copy ctor " << endl;
    }
    Foo(const Foo&& f) : data(f.data)
    {
        cout << "move ctor" << endl;
    }
    ~Foo()
    {
        cout << "Foo destructed with " << data << endl;
    }
};

int Bar(Foo f)
{
    cout << "f.data = " << f.data << endl;
    return f.data * 2;
}

int main()
{
    Foo f1(10);
    Foo f2(Bar(std::move(f1)));
}

如果我使用Microsoft Visual Studio 2015社區編譯並運行上面的代碼,我會得到以下輸出:

Foo constructed with 10
move ctor
f.data = 10
Foo destructed with 10
Foo constructed with 20
Foo destructed with 20
Foo destructed with 10

但是,如果我使用gcc 6.1.1和--std = c ++ 14編譯並運行代碼,我會得到以下輸出:

Foo constructed with 10
move ctor
f.data = 10
Foo constructed with 20
Foo destructed with 10
Foo destructed with 20
Foo destructed with 10

Bar()返回之后,gcc調用f的析構fBar()的參數,而msvc在返回之前調用析構函數(顯然),或者至少在f2的構造函數之前調用析構函數。 f應該被破壞,根據C ++標准?

他們沒事; 這取決於。 標准似乎沒有具體說明。

來自[expr.call] / 4 (這個措辭可以追溯到C ++ 98);

參數的生命周期在定義它的函數返回時結束。 每個參數的初始化和銷毀​​發生在調用函數的上下文中。

CWG#1880 ;

WG決定不確定參數對象是在調用之后立即銷毀還是在調用所屬的完整表達式結束時銷毀。

g ++(和clang)和MSVC的行為都是正確的,實現可以自由選擇一種方法而不是另一種方法。

這就是說,如果您擁有的代碼依賴於這種排序,我會改變它以使排序更具確定性 - 正如您所見,它會導致細微的錯誤。


這種行為的簡化示例是;

#include <iostream>
struct Arg {
    Arg() {std::cout << 'c';}
    ~Arg() {std::cout << 'd';}
    Arg(Arg const&)  {std::cout << 'a';}
    Arg(Arg&&)  {std::cout << 'b';}
    Arg& operator=(Arg const&)  {std::cout << 'e'; return *this;}
    Arg& operator=(Arg&&)  {std::cout << 'f'; return *this;}
};
void func(Arg) {}
int main() {
    (func(Arg{}), std::cout << 'X');
    std::cout << std::endl;
}

Clang和g ++都產生cXd和MSVC產生cdX

暫無
暫無

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

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