私は何か変わったことに気づいたときに、新しい演算子と削除演算子でオーバーロードしていました。C++での文字列割り当て
私が持っている:
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; }
を私が行うとき:
int main() { int* x = new int(1); std::cout << *x << std::endl; delete x; return EXIT_SUCCESS; }
予想どおりにすべてが動作し、私が取得:
Allocating memory... 1
しかし、私はやるとき:
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
、私が行うとき:
int main() { std::string s = "Hello world"; return EXIT_SUCCESS; }
私はまだ
Allocating memory...
を入手します!最後に、私は:
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;
...
}
そうそう。プログラミングはクールです。
注: 'malloc' /' free'と 'new' /' DELETE' - –
なぜドンペアです。あなたはデバッガを使い、誰がそれを呼んでいるのかを見るためにあなたの 'operator new'を壊しますか?ストリームはメモリも割り当てます。 –
'std :: string'の全体点は、' char * 'をラップして自分自身で管理することです。したがって、 'std :: string'を作成すると、実際の文字を格納するためにメモリが割り当てられます。コンストラクタはカスタムアロケータをとることもできます。 – BoBTFish