代码之家  ›  专栏  ›  技术社区  ›  StoryTeller - Unslander Monica

为什么STD::String::在现代C++中数据仍然受到限制?

  •  1
  • StoryTeller - Unslander Monica  · 技术社区  · 5 年前

    std::basic_string::data 有以下要求 its specification

    [字符串访问器] (强调我的)

    const charT* c_str() const noexcept;
    const charT* data() const noexcept;
    

    退换商品 一个指针 p 这样 p + i == &operator[](i) 对于每个 i 在里面 [0, size()] .

    复杂性 :恒定时间。

    要求 : 程序不应改变存储在字符数组中的任何值 .

    这在C++ 03中是有意义的。 c_str 因为它不必返回指向实际字符串缓冲区的指针, data 因为cow是一种可能的实现策略。即使缓冲区不是真的常量,修改 数据 会干扰奶牛的不变量。

    但是因为C++ 11牛被禁止, CSTR 数据 返回同一个指针,它指向缓冲区 operator[] 允许修改。为什么要通过 const_cast<CharT*>(s.data()) 仍然明确未定义的行为?有什么实际的原因吗?

    0 回复  |  直到 5 年前
        1
  •  8
  •   Nicol Bolas    5 年前

    我不是说警察 std::string ,但一个非常规。

    这就是为什么这个陈述存在(甚至在C++ 17中仍然存在的时候) const data 增加了)。因为 数据 我不知道

    在优化的小字符串中 string 实施 一串 对象本身存储一个字符数组。如果 一串 对象已声明 康斯特 ,那么它的子对象也是。 Modifying objects declared as const is UB

    相比之下, vector::data 没有这样的声明,因为 const vector 总是 heap分配它的数组。所以当数组在逻辑上 康斯特 从外部来看,它在技术上定义良好(但实际上, 真的? 不应该)去 const_cast 来自 康斯特 矢量:数据 ,因为您修改的对象不是创建为 康斯特 .

    如果 basic_string::data 如果没有这样的声明,基于sso的实现将是不可能的,因为它将 合法的 修改 const string ,就像修改 常量向量 . 但修改它是不合法的,因为它可能是 康斯特 对象,其数据存储在内部。