2013-07-23 24 views
6

私は何か変わったことに気づいたときに、新しい演算子と削除演算子でオーバーロードしていました。C++での文字列割り当て

  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 ::文字列(まあ、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; 

    ... 

} 

そうそう。プログラミングはクールです。

+0

注: 'malloc' /' free'と 'new' /' DELETE' - –

+1

なぜドンペアです。あなたはデバッガを使い、誰がそれを呼んでいるのかを見るためにあなたの 'operator new'を壊しますか?ストリームはメモリも割り当てます。 –

+2

'std :: string'の全体点は、' char * 'をラップして自分自身で管理することです。したがって、 'std :: string'を作成すると、実際の文字を格納するためにメモリが割り当てられます。コンストラクタはカスタムアロケータをとることもできます。 – BoBTFish

答えて

5

スタティックメモリであり、このコンストラクタはCopies the null-terminated character sequence (C-string) pointed by s.です。コンストラクタはそのコピーを格納するためにメモリを割り当てます。

+0

最後の文の*あなた*が混乱している、それは良い言い方をするだろう*従って 's'はコピーを格納するためにメモリを割り当てる必要がありますが、' s 'なのでコンストラクタのパラメータ名を変更することをお勧めします。 –

+0

今は良いですか? – hivert

+0

(私には少なくとも)、おかげでもっとよく見えます。 –

1
std::string s = "Hello world"; 

右側はあなたが

std::string s = "Hello world"; 

を書くときあなたはコンストラクタstring (const char* s);、の仕様を呼び出している、 sコンストラクタは、新しいメモリコピーに "Hello World" を割り当て

0

std :: stringは、Cスタイルの文字列をカプセル化する構造体です。

最初の割り当ては、文字列コンテナ構造に対して行われます。
2番目の割り当ては、文字列構成で作成された文字列のコピーです。

0

stringオブジェクト自体は、newを使用して実際の文字のスペースを割り当てます。これは文字列のコンストラクタで行われます。

3

例3:newがポインタを返すので、std::string sの代わりにstd::string *sの代わりに、最初の注意が必要です。

使用gdbが私がのstd :: coutの行にブレークポイントを設定し、2つのコールbacktraced:

最初のものは、あなたのコードに書いたnewです。 二つ目は、(私の場合)so.6のlibstdC++内から呼ばれるように行われます

(gdb) backtrace 
#0 operator new (size=36) at test.cpp:6 
#1 0x00007ffff7b78a89 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&)() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#2 0x00007ffff7b7a495 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag)() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#3 0x00007ffff7b7a5e3 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#4 0x0000000000400da1 in main() at test.cpp:20 
+0

+1だけでなく、調査のヒントを与えるために+1。 –

関連する問題