c++ - C++中的字符串分配

标签 c++ string memory

当我注意到一些奇怪的事情时,我正在玩重载 new 和 delete 运算符。

  1. 我有:

    void* operator new(size_t size)
    {
        std::cout << "Allocating memory..." << std::endl;
    
        void* p = malloc(size);
    
        if (NULL == p)
        {
            throw std::bad_alloc();
        }
    
        return p;
    }
    
  2. 当我这样做时:

    int main()
    {
        int* x = new int(1);
        std::cout << *x << std::endl;
        delete x;
        return EXIT_SUCCESS;
    }
    

    一切都按预期进行,我得到:

    Allocating memory...
    1
    
  3. 但是当我这样做的时候:

    int main()
    {
        std::string* s = new std::string("Hello world");
        std::cout << *s << std::endl;
        delete s;
        return EXIT_SUCCESS;
    }
    

    我得到:

    Allocating memory...
    Allocating memory...
    Hello world
    
  4. 事实上,当我这样做的时候:

    int main()
    {
        std::string s = "Hello world";
        return EXIT_SUCCESS;
    }
    

    我仍然得到 Allocating memory...!

  5. 最后,我做了:

    int main()
    {
        std::string s = "Hello world";
        std::cout << &s << std::endl;
        while (true);
    }
    

    得到类似的东西:

    $ ./test &
    [1] 8979
    Allocating memory...
    0xbfc39a68
    $ cat /proc/8979/maps | grep stack
    bfc27000-bfc3c000 ... [stack]
    

    所以现在我确定 s 变量已分配到堆栈上...但是,什么调用了 new 运算符?我最好的猜测是它与实际文字的内存分配有关,“Hello world”...但它应该是静态内存,new都是关于动态内存的。

这是怎么回事?

更新

在阅读评论并亲自调试示例后,我想得出的结论是,一旦调用字符串构造函数,它就会在堆上为其内部实现分配内存。这可以通过跟踪 new 调用看出:

(gdb) b 13 // that's the std::cout << "Allocating memory..." << std::endl; line
(gdb) r
... Breakpoing 1, operator new (size=16) at test.cpp:13 ...
(gdb) backtrace
#0 operator new (size=16) at main.cpp:13
#1 std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) () from /usr/lib/libstdc++.so.6
...

并阅读 std::string(嗯,basic_string.tcc)源代码:

template<typename _CharT, typename _Traits, typename _Alloc>
typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
basic_string<_CharT, _Traits, _Alloc>::_Rep::
_S_create(size_type __capacity, size_type __old_capacity,
          const _Alloc& __alloc)
{

   ...

    void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
   _Rep *__p = new (__place) _Rep; // Bingo!
   __p->_M_capacity = __capacity;

   ...

}

是的。编程很酷。

最佳答案

当你写作时

std::string s = "Hello world";

你正在调用构造函数string (const char* s);,这个构造函数的规范是复制s指向的空终止字符序列(C-string)。 因此构造函数分配内存来存储拷贝。

关于c++ - C++中的字符串分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17810329/

相关文章:

c++ - 如何将 vector 插入多维 vector ?

c++ - 如何正确地将接口(interface)委托(delegate)给 C++ 中的姊妹类?

c++ - 关于虚幻引擎 4 中 PlayAnimMontage 代码的问题

java - 检查字符串是否包含子字符串,不使用 java 预定义方法

c++ - 为什么我的程序内存不释放?

python - 查找内存使用情况、CPU 使用情况、运行 python 脚本的执行时间

c++ - 带有 std::shared_ptr 的数组索引符号到数组

带有 char 和 wchar_t 的 C++ 正则表达式?

javascript - Chai 期望列表包含字符串类型的项目

c++ - 我需要取消分配 vector 中的对象指针吗?