使用两个字符串字面量构造含自定义构造函数的结构体vector崩溃,原因何在?
C++程序输出推测与问题分析提示
#include <vector> #include <string> #include <exception> #include <iostream> int main() { try { struct X { explicit X(int) {} X(std::string) {} // Just to confuse you more... }; std::vector<X>{"a", "b"}; } catch (std::exception& x) { std::cerr << x.what(); } }
请推测以上简单C程序的输出。我无法推测其输出,为此花费了一天时间排查,最终从复杂的实际代码中提炼出这段示例。我仍未弄清问题所在,能否提供提示?我已不再从事专业C开发。注:该代码在最新版MSVC(/W4)和GCC(-Wall)下均可干净编译,二者语义输出一致。
核心提示
- C++规则限制:不允许连续两次用户自定义的隐式转换。
const char*要转为X,需要先转std::string(一次用户自定义转换),再转X(第二次),这条路径不合法。 - 基于上述限制,
std::vector<X>{"a", "b"}不会匹配vector的std::initializer_list构造函数——因为列表里的const char*无法隐式转换为X。 - 编译器会转而匹配
vector的模板构造函数:template <class InputIterator> vector(InputIterator first, InputIterator last),把两个const char*当成迭代器处理。 - 这个构造函数会尝试遍历
"a"到"b"的内存范围,但"a"和"b"是独立的字符串字面量,对应的地址范围是非法的内存区域,遍历会触发未定义行为,多数实现中会抛出std::exception派生的异常(比如内存访问错误相关的异常)。 - 编译通过的原因:遍历过程中解引用迭代器得到
char值,char可隐式转为int,而X的explicit X(int)构造函数允许在直接初始化(如列表初始化)场景下被调用,因此能完成X对象的构造。
内容的提问来源于stack exchange,提问作者Sz.
相关产品推荐
相关产品推荐

