2017-09-05 95 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>的糖衣。

对坏模式有一点保护(它会抛出而不是崩溃,这在很多程序中都是相同的)。

相关问题