移动initialization_list元素被认为是危险的
moving elements of an initialization_list considered dangerous?
之前关于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
的几乎所有安全用例。
相关文章:
- 为什么rand()的使用被认为是不好的
- 为什么 std::shared_ptr 被认为是"heavy"和"expensive",但 std::array "same perfprmance as plain (c-style) arrays
- 一个C头文件可以被认为是一个接口吗
- 为什么const char*和const char[]作为函数参数被认为是等价的
- 为什么12.0==11.999999999999999999被认为是真的
- 这会被认为是糟糕的编程实践吗?
- 为什么这被认为是恒定的?
- 抽象类/接口中的空方法是否被认为是一种好的做法?
- 如果我具有调用其其他实例之一的超载函数,它是否被认为是递归功能
- std::unique_ptr可以被认为是一个monad吗?
- C++ 指向类的指针和/或引用是否被认为是"movable"?
- 使用自定义宏来简化 cin 和 cout 语句等内容被认为是更好还是更差
- 使用成员函数更改对象或返回并分配它是否被认为是更好的做法?
- 我很难修复我认为是双重免费的东西
- 使用 #define 被认为是"bad practice"吗?
- 是一个被认为是不同类型的班级内部的正向声明
- 这被认为是有效的C 11还是C 14?还是GCC/Clang弄错了
- 为什么这个嵌套的 lambda 不被认为是 constexpr?
- 移动initialization_list元素被认为是危险的
- 从安全角度来看,在 Windows 中使用管道是否被认为是危险的