我想傳遞一個數組到一個函數,並防止每次寫「std :: unique_ptr」,並使內聯建設成爲可能,我介紹了一個typedef( ItemList)來爲數組別名。C++ 11列表初始化在Visual Studio 2013奇怪的行爲
#include <iostream>
#include <memory>
class Base {
public:
Base()
{
std::cout << "Base ctor" << std::endl;
};
virtual ~Base()
{
std::cout << "Base dtor" << std::endl;
};
};
typedef std::unique_ptr<Base> ItemList[];
template<typename T>
class Derived : public Base {
T val;
public:
Derived(T i)
{
val = i;
std::cout << "Derived ctor" << val << std::endl;
};
~Derived()
{
std::cout << "Derived dtor" << val << std::endl;
};
};
void dummyFunc(ItemList)
{
}
void testFunc()
{
dummyFunc(ItemList{
std::make_unique<Derived<int>>(2),
std::make_unique<Derived<float>>(3.0f)
});
}
//Entry point
int main()
{
testFunc();
return 0;
}
這可以按照打算在調試版本中打印和打印;
Base ctor
Derived ctor2
Base ctor
Derived ctor2
Derived dtor2
Base dtor
Derived dtor2
Base dtor
到目前爲止好。但是當我以釋放模式(使用所有本機編譯器)構建它時,
Base ctor
Derived ctor2
Base ctor
Derived ctor3
Derived dtor2
Base dtor
退出數組生命週期後,數組中的第二項不會被破壞。 使其按照我的預期工作的唯一方法是使用C++ 03樣式初始化或調試模式;
ItemList tmpList = {
std::make_unique<Derived<int>>(2),
std::make_unique<Derived<float>>(2.0f)
};
dummyFunc(tmpList);
這導致了預期的行爲(所有析構函數被調用)。
我還沒有用任何其他編譯器測試過,但這是預期的行爲?我做錯了什麼,或者我錯過了什麼?
更新:
有趣dtors被稱爲與基地實例預期;
dummyFunc(ItemList{
std::make_unique<Base>(),
std::make_unique<Base>()
});
輸出;
Base ctor
Base ctor
Base dtor
Base dtor
剛剛初始化數組(無函數調用)的行爲與函數調用的行爲相同。
有趣......它在win和mac默認編譯器上編譯。不確定在Mac上的發佈行爲,但會檢查。還沒有嘗試過你的解決方案。另一方面,我不確定它是否真的應該抱怨使用臨時數組。這是我的問題,警告會是一個更好的行爲。應該檢查這種行爲的標準。 –
@AliNaciErdem取一個右值的地址是非法的,參考標準:「一元&運算符的結果是一個指向其操作數的指針。操作數應該是一個左值或者是一個合格的id。關於VS在release中的行爲,我更新了我的答案。 – AntiClimacus
這仍然不能解釋行爲。如果它被轉換爲第一個元素的指針,那麼爲什麼第一個元素被破壞?我沒有明白。沒關係,如果對象在被傳遞給func之前被破壞,但它應該被銷燬,因爲它被分配到堆棧中。 –