编辑:在我们开始之前,这个问题不是关于正确使用std::initializer_list
; 它是关于在需要方便的语法时应该传递的内容。感谢您留在主题上。
C++11 引入std::initializer_list
了定义接受花括号初始化列表参数的函数。
struct bar {
bar( char const * );
bar( int );
} dog( 42 );
fn foo( std::initializer_list< bar > args );
foo( { "blah", 3, dog } );
语法很好,但在底层它由于各种问题而令人反感:
它们不能被有意义地移动。上述函数必须
dog
从列表中复制;这不能转换为移动构造或省略。根本不能使用只移动类型。(嗯,const_cast
实际上是一个有效的解决方法。如果有一篇关于这样做的文章,我想看看。)也没有
constexpr
语义。(这将在 C++1y 中实现。不过,这是一个小问题。)const
不像其他地方那样传播;initializer_list
永远是,但它的const
内容永远是。(因为它不拥有它的内容,它不能授予对副本的写访问权,尽管在任何地方复制它很少是安全的。)该
initializer_list
对象不拥有它的存储空间(哎呀);它与提供存储的完全独立的裸数组 (yikes) 的关系被模糊地定义 (yikes) 为对绑定临时的引用的关系 (quadruple yikes)。
我相信这些事情会在适当的时候得到修复,但现在有没有最佳实践来获得优势而不需要硬编码initializer_list
?是否有任何关于解决直接依赖它的文献或分析?
显而易见的解决方案是通过值传递标准容器,例如std::vector
. 一旦将对象从 复制到其中initializer_list
,它就会被移动构造为按值传递,然后您可以将内容移出。一个改进是在堆栈上提供存储。一个好的库可能能够提供 、 和 的大部分优点,initializer_list
甚至无需使用前者。array
vector
有资源吗?