【问题标题】:shrinking stl string to a capacity of less than 15 characters将 stl 字符串缩小到小于 15 个字符的容量
【发布时间】:2018-10-29 02:06:39
【问题描述】:

考虑 std::string 和容量

 std::string aString = "12345678901234567890";
 std::cout << aString.capacity() << std::endl; // capacity is 20
 aString.clear();
 std::cout << "size: " << aString.size() << std::endl;
 std::cout << aString.capacity() << std::endl; // capacity is 20
 aString.shrink_to_fit();
 std::cout << aString.capacity() << std::endl; // capacity is 15?
 std::string newString;
 std::cout << newString.capacity() << std::endl; // capacity is 15?

最小容量是 15 个字符吗?有没有办法把它缩小到字符串的实际大小?

【问题讨论】:

  • 考虑到今天的主要实现都使用短字符串优化,我不确定你会得到什么好处。
  • 您在此处观察到的一切都是实现定义的行为,并且因编译器而异。因此,这绝对没有任何用处。这个特定编译器的实现可能涉及所谓的“短字符串优化”,它允许将最多 15 个字符的字符串存储为std::string 本身的一部分,而不是动态分配。但是,正如我所说,这是一个内部编译器实现行为,你不能依赖它。
  • @SamVarshavchik 这就是我所担心的。 Fwiw,它是 gcc 4.8,-std=gnu++11
  • 这并没有解决问题,但是您真的需要std::endl 需要的额外内容吗? ’\n’ 结束一行。
  • 我在这里看不到任何需要“担心”的东西。这是一个相当常规的字符串实现。

标签: c++ c++11 stl


【解决方案1】:

std::string 的一些实现使用“短字符串优化”,它使用字符串本身的空间而不是动态分配的内存来存储小字符串的内容。因此,您不能缩小字符串,因为该内存是字符串本身的一部分。

【讨论】:

    【解决方案2】:

    这在 msvc2017 basic_string 实现中是不可能的,因为构造一个空的 std::string 将分配至少 15 个字符。

    更多详情: std::string.capacity() 返回_Myres,表示当前分配的存储长度

    // Implementation of std::string.capacity()
    _NODISCARD size_type capacity() const noexcept
        {   // return current length of allocated storage
        return (this->_Get_data()._Myres);
        }
    
    // Construct an empty string would call _Tidy_init() method
        basic_string() _NOEXCEPT_COND(is_nothrow_default_constructible_v<_Alty>)
            : _Mybase()
            {   // construct empty string
            _Tidy_init();
            }
    // Moreover, initialize _Myres by enum constant value
    void _Tidy_init()
        {   // initialize basic_string data members
        auto& _My_data = this->_Get_data();
        _My_data._Mysize = 0;
        _My_data._Myres = this->_BUF_SIZE - 1;
        // the _Traits::assign is last so the codegen doesn't think the char
        // write can alias this
        _Traits::assign(_My_data._Bx._Buf[0], _Elem());
        }
    // _BUF_SIZE stands for literal number 16 (std::cout<<std::string::_BUF_SIZE;)
    enum
        {   // length of internal buffer, [1, 16]
        _BUF_SIZE = 16 / sizeof (value_type) < 1 ? 1
            : 16 / sizeof (value_type)};
    

    【讨论】:

      猜你喜欢
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-19
      • 2013-10-09
      相关资源
      最近更新 更多