You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用两个字符串字面量构造含自定义构造函数的结构体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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 07:16:16