为何用const char字面量初始化std::vector时未调用移动构造函数?
你遇到的核心问题和std::initializer_list的特性直接相关,具体拆解如下:
初始化列表元素的本质
当你写{"hello", "world"}时,编译器会先将字符串字面量转换为std::string,再打包成std::initializer_list<std::string>对象。而std::initializer_list的内部是一个const T类型的数组,也就是说列表里的每个std::string都带有const属性。移动构造的调用限制
std::string的移动构造函数签名为string(string&& other),它要求传入的参数是可修改的右值(或能转换为右值的非const对象)。但std::initializer_list里的元素是const的,无法绑定到string&&这种非const右值引用上——毕竟移动操作会修改源对象(转移其内存资源,将源对象置空),而const对象不允许被修改。编译选项的实际作用
你用-fno-elide-constructors禁用了复制消除,但这个选项只影响那些原本可被优化消除的复制/移动操作。这里从一开始就没有触发移动构造的可能,所以即使禁用优化,编译器也只能调用std::string的复制构造函数(string(const string& other)),因为它接受const左值引用,正好匹配std::initializer_list里的const元素。
如果要验证移动构造的调用逻辑,可以显式创建非const临时对象并转换为右值:
std::vector<std::string> my_vec {std::move(std::string("hello")), std::move(std::string("world"))};
内容的提问来源于stack exchange,提问作者Suat Mutlu

