4

Javaでしばらく過ごした後、C ++に戻ることにしました。今では、C++で文字列がどのように機能するかについてかなり混乱しています。

まず、次の関数があるとします。

void fun() {
   int a = 1;
   Point b(1,2);
   char c[] = "c-string";
}

私が理解しているように、aそしてbスタックに割り当てられています。c(ポインタ)もスタックに割り当てられますが、コンテンツ( "c-string")はヒープ上で問題なく動作します。

Q1:機能終了時に内容がc自動的に割り当て解除されますか?fun

次に、C++があるとしましょうstring

void fun2() {
  (1) string s = "c++ string";
  (2) s += "append";
  (3) s = "new contents";
  (4) s = "a" + s + "c";
}

文字列のドキュメントは、文字列がどのように機能するかについてあまり具体的ではないため、ここに質問があります。

Q2:終了後、内容はs自動的に割り当て解除されfun2ますか?

Q3: 2つの文字列を連結するとどうなりますか?メモリ使用量を気にする必要がありますか?(2行目)

Q4:文字列の内容を上書きするとどうなりますか(3行目)-メモリについてはどうですか?心配する必要がありますか?最初に割り当てられたスペースは再利用されますか?

Q5:このような文字列を作成するとどうなりますか(4行目)。高いですか?文字列リテラル("a""c")は(Javaのように)プールされますか、それとも最終的な実行可能ファイル全体で繰り返されますか?

私が最終的に学ぼうとしているのは、C++で文字列を正しく使用する方法です。

これを読んでくれてありがとう、
Queequeg

4

4 に答える 4

8

私が理解しているように、aとbはスタックに割り当てられます。c(ポインタ)もスタックに割り当てられますが、コンテンツ( "c-string")はヒープ上で問題なく動作します。

それは間違っています、それらはすべて自動メモリ(スタック)に住んでいます。charアレイですら。C ++では、文字列はタイプのオブジェクトですstd::string

Q1:関数funが終了すると、cの内容は自動的に割り当て解除されますか?

はい。

Q2:fun2の終了後、sの内容は自動的に割り当て解除されますか?

はい。

Q3:2つの文字列を連結するとどうなりますか?メモリ使用量を気にする必要がありますか?(2行目)

それらは連結され、メモリは自動的に管理されます。(私たちが話しているのであってstd::string、そうではないと仮定しchar[]ますchar*

Q4:文字列の内容を上書きするとどうなりますか(3行目)-メモリについてはどうですか?心配する必要がありますか?最初に割り当てられたスペースは再利用されますか?

実装の詳細。再利用できます。前のメモリが新しいコンテンツを保持できない場合は、再割り当てできます。

Q5:このような文字列を作成するとどうなりますか(4行目)。高いですか?文字列リテラル( "a"、 "c")は(Javaのように)プールされますか、それとも最終的な実行可能ファイル全体で繰り返されますか?

文字列リテラルはプールできますが、必須ではありません。std::stringstream大規模な連結の場合、代わりに(Javaと同様に)使用するのが通常です。ただし、最初にプロファイルを作成し、時期尚早の最適化を行わないでください。ただし、どちらも文字列リテラルではありません。

char* pStr = "this is a string literal";

これは読み取り専用メモリにあり、変更できません。

私が最終的に学ぼうとしているのは、C++で文字列を正しく使用する方法です。

を使用しstd::stringます。

于 2012-09-04T06:26:32.760 に答える
8

cポインタではありません。配列です。角かっこが付いているのに対し、ポインタには星が付いているため、配列であることがわかります。は自動変数であるためc、手動による有効期間やメモリ管理は必要ありません。

Ad Q2:sも自動変数であり、適切に設計されたクラスタイプであるため、手動で何も処理する必要がないことを意味します。

広告Q3:ローカル文字列オブジェクトは、新しい文字列を含むように適切に変更されます。その過程で、連結式の期間中、一時的な文字列オブジェクトが存在する場合と存在しない場合があります。(これは4行目にのみ適用されます。2行目には一時的なものはありません。)

広告Q4:すべてが正常で、期待どおりに機能します。Q2を参照してください。割り当ての詳細に応じて、元のメモリが使用される場合と使用されない場合があります。あなたの例では、元のメモリはおそらく上書きされます。のような場合s = std::string("hello");、2つの文字列のバッファが交換される可能性があります。

Ad Q5:文字列リテラルは読み取り専用のグローバル定数であり、コンパイラーはこれを任意の方法で実装できます。詳細はそれほど重要ではありません。あなたは間違いなくで目的のstringオブジェクトになりsます。Q3re一時オブジェクトを参照してください。

「C++で文字列を使用する方法を学ぶ」には、文字列を使用してください。それらを整数のように扱います。正しいでしょう。標準ライブラリの利点は、「物事がどのように機能するか」を本当に知る必要がないことです。標準ライブラリクラスを慣用的なC++方式で使用すると、すべてのリソース管理が自動的かつ効率的に行われます。

于 2012-09-04T06:29:29.530 に答える
1

Q1:はい、割り当てが解除されています。文字配列は関数のスタックにあります。

Q2:はい、std::string自動的に割り当てられたすべての変数の場合と同様に、スコープを離れるときに発生する破棄時にすべてのリソースを解放します。

Q3:いいえ、プロファイリングで指示がない限り、心配する必要はありません。

Q4:心配する必要はありません。元のスペースは再利用される場合とされない場合があります。いずれの場合も、文字列によって使用されるすべてのスペースは、関数を終了するときに割り当てが解除されます。

Q5:最適化を考えると、コンパイラーは、XがYよりも高価であるかどうかを確認する唯一の方法は、両方をプロファイリングすることです。

于 2012-09-04T06:26:20.217 に答える
0

Q1リテラル"c++ string","append","new contents","a","c"は静的メモリにあることに注意してください

于 2012-09-04T06:29:57.503 に答える