移动initialization_list元素被认为是危险的

moving elements of an initialization_list considered dangerous?

本文关键字:认为是 危险 元素 initialization list 移动      更新时间:2023-10-16

之前关于SO的问题(1和2)似乎表明,对std::initializer_list元素应用std::move可能会导致UB。事实上,std::initializer_list迭代器会阻止有效移动,因为它们引用了常量元素。原因是编译器可能会使用静态只读内存来存储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 标准说:"[ 注意:如果可以这样分配具有相同初始值设定项的显式数组,则实现可以自由地在只读内存中分配数组。—尾注]"。似乎这是"具有相同初始值设定项的显式数组"无法以只读方式分配的一种情况。所以它可能具有自动存储功能。

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

如果基础对象不是const限定的,则可以const_cast限定,但只有引用是限定的。

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

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

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