2017-09-05 97 views
3

如果我有一個類型是std::is_nothrow_move_constructible,我需要將它存儲在std::anystd::variant,你會推薦使用哪一個?爲什麼?哪一個會給最少的開銷?編輯:std::variantstd::any有什麼不同的用例?std :: variant vs std ::任何當類型是移動可構造

class MyType 
{ 
public: 
    MyType(const MyType&) = default; 
    MyType(MyType&&) = default; 
    MyType() = default; 
}; 

int main(int argc, char* argv[]) 
{ 
    static_assert(std::is_nothrow_move_constructible<MyType>::value, "Not move constructible"); 
    return 0; 
} 
+9

它們被用於不同的目的。 –

+0

@RinatVeliakhmedov你想介紹一下嗎?我不確定不同的用例。 – 0xBADF00

+3

當你知道可以存儲的類型(基本上是一個更安全的聯合)時,使用std :: variant,當你不知道的時候std :: any。 – ralismark

回答

5

如果您知道類型,請使用std::variant。在這種情況下,您知道所有可能的類型,並使用std::variant::visit()將訪問者應用於變體。

如果您不需要,請使用std::any。處理通用類型時可以考慮這一點。換句話說,當類型不知道apriori時。


哪一個將給予至少開銷?

std::variant,不能使用堆。這是不允許的。如果沒有動態分配,沒有辦法真正擁有一個包含自身可能變體的結構,因爲如果靜態聲明,這樣的結構可以很容易地顯示爲無限大。 Source

相比之下,std::any可以這樣做。結果,第一個將有更快的建設和複製操作。

+0

我很好奇,如果你甚至不知道它的可能類型,你如何使用'void *'或者'std :: any'? –

+0

@PasserBy檢查此[示例](https://stackoverflow.com/documentation/c%2b%2b/7894/stdany#t=201709051128521966086)。不過,我明白你的觀點。也許我的答案的部分混淆了讀者,應該刪除。你怎麼看? – gsamaras

+0

看一下這個例子,IMO更加引人注意的使用'std :: any'的原因恰恰是因爲它使用了一定量的內存,因爲類型(顯然)最終是已知的。 –

2

std::any爲堆中的值分配存儲空間。而std::variant不使用堆,因此它在構造和複製方面效率更高,更容易緩存,因爲值直接存儲在對象中,並且不涉及間接和虛擬功能來訪問它。

std::variant的界面更加豐富和易於使用。

std::any僅當std::variant由於某種原因不能使用時纔有用。

+0

檢查[this](https://stackoverflow.com/a/45419725/4832499)簡單實現'std :: variant'。據我所知,沒有辦法繞過'std :: visit'的查詢表/虛函數調用,這種或那種方式會有間接性。 TLDR緩存友好聽起來不對 –

+0

@PserserBy您的陳述是錯誤的,訪問不需要使用任何虛擬功能。 –

+0

你可以舉一個例子來說明如何實現'std :: visit'而不用任何形式的間接?我真的不知道一種方式 –

2

類型安全,鬆耦合和易於維護的原因:

喜歡variant超過any如果你所能。

因爲實質上,std::any是圍繞可複製std::unique_ptr<void, some_deleter>的糖衣。

對壞模式有一點保護(它會拋出而不是崩潰,這在很多程序中都是相同的)。

相關問題