初始化列表的移动元素被认为是危险的?

时间:2013-09-16 06:15:31

标签: c++ c++11 move-semantics initializer-list

之前提出的问题(12)似乎暗示将std::move应用于std::initializer_list的元素可能会导致UB。实际上,std::initializer_list迭代器阻止了有效移动,因为它们引用了const元素。原因是编译器可能使用静态只读内存来存储initializer_list的底层数组。

我认为这种观点太有限了,我想知道这里的专家是否同意。 IMO,以下代码不可能使用只读存储。

void attempt_move(std::initializer_list<std::string> list) {
  // must use const std::string &. Can't move.
}
int main(int argc, char *argv[])
{
  if(argc >= 4)  
    attempt_move({ argv[1], argv[2], argv[3] }); 
}

底层std::string数组不可能存在于只读存储中,因为AFAIK只读存储必须在main之前初始化,并且argv参数不知道时间。实际上,C ++ 11标准说:“[注意:如果可以如此分配具有相同初始化程序的显式数组,则实现可以在只读存储器中自由分配数组。-end note]”。似乎这是一种情况,其中“具有相同初始化程序的显式数组”不能以只读方式分配。所以它可能有自动存储。

如果这是真的,似乎由于std::initializer_list的常量迭代器而丢失了移动字符串对象的机会。有解决方法吗?

1 个答案:

答案 0 :(得分:0)

如果基础对象不是const_cast - 合格,但只有参考资格,您可以const取消资格。

const资格不一定与静态存储在物理ROM中相同。在大多数情况下,编译器只是认为任何人都不会修改对象是安全的。

是的,这是未定义的行为。这被认为是initializer_list的严重缺点。希望它能为C ++ 17修复。

是的,如果移动是这些元素发生的唯一事情,你可能会侥幸逃脱它,事实上它几乎涵盖了阳光下initializer_list的所有安全用例。