之前提出的问题(1和2)似乎暗示将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
的常量迭代器而丢失了移动字符串对象的机会。有解决方法吗?
答案 0 :(得分:0)
如果基础对象不是const_cast
- 合格,但只有参考资格,您可以const
取消资格。
但const
资格不一定与静态存储在物理ROM中相同。在大多数情况下,编译器只是认为任何人都不会修改对象是安全的。
是的,这是未定义的行为。这被认为是initializer_list
的严重缺点。希望它能为C ++ 17修复。
是的,如果移动是这些元素发生的唯一事情,你可能会侥幸逃脱它,事实上它几乎涵盖了阳光下initializer_list
的所有安全用例。