-
Notifications
You must be signed in to change notification settings - Fork 0
6. Zigzag Conversion #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| #include <chrono> | ||
| #include <iostream> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| using namespace std; | ||
|
|
||
| class Solution { | ||
| public: | ||
| string convert(string s, int numRows) { | ||
| if (numRows == 1) { | ||
| return s; | ||
| } | ||
| vector<string> string_per_row(numRows); | ||
|
|
||
| bool is_downforward = true; | ||
| int row = 0; | ||
| for (char letter : s) { | ||
| string_per_row[row] += letter; | ||
| if (is_downforward) { | ||
| row++; | ||
| } else { | ||
| row--; | ||
| } | ||
|
|
||
| if (row == numRows - 1) { | ||
| is_downforward = false; | ||
| } else if (row == 0) { | ||
| is_downforward = true; | ||
| } | ||
| } | ||
|
|
||
| string converted = ""; | ||
| converted.reserve(s.size()); | ||
| for (const auto& str : string_per_row) { | ||
| converted += str; | ||
| // std::cout << converted.size() << "/" << converted.capacity() << std::endl; | ||
| } | ||
| return converted; | ||
| } | ||
| }; | ||
|
|
||
| int main() { | ||
| Solution sol; | ||
| string input = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk"; | ||
| int numRows = 3; | ||
|
|
||
| // 計測開始 | ||
| auto start = std::chrono::high_resolution_clock::now(); | ||
| string result = sol.convert(input, numRows); | ||
| //std::cout << "変換後の文字列: " << result << std::endl; | ||
|
|
||
| // 計測終了 | ||
| auto end = std::chrono::high_resolution_clock::now(); | ||
|
|
||
| // 経過時間(ミリ秒) | ||
| //std::chrono::duration<double> elapsed = end - start; | ||
| // std::cout << "処理時間: " << elapsed.count() << " 秒" << std::endl; | ||
| // 経過時間(マイクロ秒) | ||
| auto elapsed_us = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count(); | ||
| std::cout << "処理時間: " << elapsed_us << " マイクロ秒" << std::endl; | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| ## ステップ1 | ||
| 手作業でするならどうするのか考えてみる | ||
| まずnumRows行の方眼紙を用意する。列数はわからないので予め用意しておくか、必要になれば広げる | ||
| sから一文字ずつ転記する | ||
| ・まずは行の1番下まで埋まるように | ||
| ・次は一文字ずつ行の1番上まで辿り着くように | ||
| この時は一文字転記したら次の列に移動 | ||
| 1番上までたどり着いたらまた行の1番下まで埋まるように文字を転記する | ||
| 上の作業が終わったら今度は列、行という順で文字を拾って組み合わせる | ||
|
|
||
| 1人1転記で作業をさせるなら、下記の情報が必要かな。 | ||
| ・下向きに作業をしているのか上むきに作業すしているのかのフラグ | ||
| ・前の作業者はどこに転記したのか | ||
|
|
||
| 1 5 9 | ||
| 2468 | ||
| 3 7 | ||
| 3にたどり着いたら、次は上むきと伝える。 | ||
| 5に辿り着いたら、次は下向きと伝える。 | ||
|
|
||
| numRowsをm、stringの長さをnとすると | ||
| 時間計算量と空間計算量どちらもO(m n) | ||
|
|
||
| ## ステップ2 | ||
| step2.cppでは下記について対応。 | ||
| ・条件分岐が多いので読み辛い | ||
| ・vector<vector<char>>で必要以上の領域を確保していないか | ||
|
|
||
| ・条件分岐が多いので読み辛い | ||
| 転換する処理を、上方向と下方向に動く処理の中から外だし。 | ||
| 移動処理が重複していたので切り離し | ||
|
|
||
| ・vector<vector<char>>で必要以上の領域を確保していないか | ||
| colはs.size()で領域を確保している | ||
| =>leetcodeの解説にミニマムで確保する方法の説明があった。 | ||
| 上から下まで下がって、また上まで上がる部分を一つのセクションを捉えると | ||
| 上から下方向にはnumRows文字 | ||
| 下から上方向には、numRows - 2文字必要で、1セクションに対してnumRows + (numRows - 2)文字必要 | ||
| 必要なセクション数は、s.size() / (2numRows - 2) | ||
| 各セクションは、numRows - 1列必要なのでs.size() / (2numRows - 2) * (numRows - 1)が最小で必要な数 | ||
|
|
||
| step2_1.cpp | ||
| step2.cppのvector<vector<char>>からvector<string>へ | ||
| Yoshiki-Iwasaさんの回答を参照 | ||
| 何度か調べた気がするが効率のいいstringの繋げ方を調べてみる | ||
|
|
||
| stringstreamは前に一度使った気がするけど、効率的でないのか。 | ||
| >Is std::stringstream any better for this purpose? | ||
| >No, iostreams are notoriously slow (in spite of theoretical possible high speed): | ||
| >you can be reasonably sure that it will be slower than most any alternative, due to flawed locale support. | ||
| https://www.reddit.com/r/cpp_questions/comments/wxiyg1/most_efficient_way_to_concatenate_strings/ | ||
|
|
||
| こちらの中でも色々議論されている | ||
| reserveを使って予め必要なメモリを確保しておけば先確保を減らすことができる。 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. こういう話、速くしたいということが目的ならば、どれくらい速くなるかを「秒」なりで具体的に概算してください。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oda There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Ryotaro25 それは秒ではないです。なぜ、秒でといっているかというと、メリットがある程度定量化できないと、その選択を取ったときのデメリットと比較ができないからです。 また、仕様上、計算量は定数時間で償却できるようにする必要があるので、普通は doubling するのが一般的です。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
秒以外の何かしらの数値でもいいと理解しておりました🙇♂️ sは1000文字にしてリアロケーションがどのように発生するのか確認
#include を用いて実行速度を計測する。 ・sは1000文字、numRows = 1000 reserveを使うことで、リアロケーションは発生しなくなったが There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. すみません、これはそれぞれどういうコードを走らせた時の何の数字ですか。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. さて、capacity の変化を見ると、合計1500文字くらい reallocation されていますね。 機械語の知識の問題になりますが、CPU の周波数が 3GHz として、150クロックくらい。1クロックで8文字ずつ(64ビット)コピーされるとすると、1200文字となっておおむね辻褄が合います。 要するに、reserve を足すと、概ね3マイクロ秒で動くコードを 50 ナノ秒コードを改善したということです。このためにこの一行足す価値ありますか。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oda
覚えておきます🙇♂️
直感に合うかどうか答えられなかったです。周波数やクロックという単語を認識しておりますが数値周りの理解ができていないので調べながら手元で計算しました。 1GHzだと、1sあたりに10^9(10億)回クロック信号が発信される。
レスポンスに対する要件を最重要とするならば入れてもいいと思いました。ただ入れることで今後、入力が1000文字以上になってくると固定値で管理しているので拡張性はないと思いました。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. そうですね。これが1ヶ月かかるプログラムのタイトなループの部分ならば半日速くなる話なので考えますね。 ただ、普通 50 ns 速くする方法というのは大量にあるので、それを全部採用していられないので、扱いやすさを優先します。 最低限、「パレート最適」、つまり、何かを改善しようとすると、何かが悪くなる、くらいにはよいコードを書きたいです。その中では比較的、コードの複雑さ(code complexity) が優先される事が多いです。 https://discord.com/channels/1084280443945353267/1262688866326941718/1346868225446641678 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. あ、もちろんどれを選ぶかは状況によります。 たとえば、標準ライブラリーだとどういう使われ方がするか分からない中で可能な限りチューニングします。Python の標準ライブラリーは一部 C で実装されていたりしますね。 |
||
| https://stackoverflow.com/questions/611263/efficient-string-concatenation-in-c | ||
|
|
||
| 今回stringの最長は1000文字。numRowsが1000の場合、一文字ずつ繋げる必要がある。 | ||
| 下記の記事によると、環境にもよるがだいたい初期は32文字まで確保されている。 | ||
| https://stackoverflow.com/questions/53216377/how-much-memory-is-allocated-to-an-uninitialized-stdstring-variable | ||
| ~~1000 / 32 ≒ 31なので、31回リアロケーションが発生する。~~ | ||
| →これは誤り。領域は確保のたびに倍のサイズになるので、6回発生 | ||
| あらかじめreserveで確保しておくと、1度ですむ。 | ||
|
|
||
| Mac OS上でテスト | ||
| sは1000文字にしてリアロケーションがどのように発生するのか確認 | ||
| capcityの変化 : 22 47 95 191 383 767 1535 | ||
|
|
||
| #include <chrono>を用いて実行速度を計測する。 | ||
| https://www.rk-k.com/archives/6973 | ||
| ・sは1000文字、numRows = 1000 | ||
| reserve無し | ||
| 処理時間: 0.000161757 秒 | ||
| reserveあり | ||
| 処理時間: 0.000206844 秒 | ||
|
|
||
| ・sは1000文字、numRows = 1000 | ||
| reserve無し | ||
| 処理時間: 3.6マイクロ 秒 | ||
| reserveあり | ||
| 処理時間: 3.6マイクロ 秒 | ||
|
|
||
| reserveを使うことで、リアロケーションは発生しなくなったが | ||
| 1000文字では、実行速度に差が見られなかった。 | ||
|
|
||
| step2_2.cpp | ||
| step2_1.cppで使っていたbool is_downforwardをint directionに置き換え | ||
| fhiyoの回答を参考 | ||
| 個人的には、boolで管理した方が理解しやすいと感じた。 | ||
| row += directionまでいかないとdirectionがどう動作するのか理解できないからか | ||
|
|
||
| ## ステップ3 | ||
| **3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** | ||
| step2_1.cppを用いる | ||
|
|
||
| ## 他の方の解法 | ||
| ・確かに、領域確保にいきなり数式が出てくると何をしているのか理解できないので | ||
| コメントで補足があった方が良さそう | ||
| ・テーブル全部埋める必要はなくて、行ごとに文字列を入れる | ||
| なるほどです。空間計算量を抑えられますね。 | ||
| https://github.com/Yoshiki-Iwasa/Arai60/pull/65/commits/fba81a9cffadbaf178b3f63871ab2ea644ec790d | ||
|
|
||
| >文字列を走査しながら各文字に行番号(ArrayListのindex番号)を振る | ||
| >`s = "PAYPALISHIRING"`, `numRows = 3` であれば `01210121012101` | ||
| こういう法則に気づけるようになりたい。ここからだとvector<string>での解法を導き出せそう。 | ||
|
|
||
| ・1行でのifや三項演算子を自分は使わないので読むのに少し苦労した。 | ||
|
|
||
| >Google Style Guide は条件が1行、中身が1行のときだけぶら下がりを許容としています。 | ||
| >時々、編集を重ねているうちに事故を起こすんですよ。 | ||
| こんな視点もあるんですね。 | ||
| https://github.com/Hurukawa2121/leetcode/pull/5#discussion_r1874549052 | ||
| https://github.com/katsukii/leetcode/pull/7/commits/53f8587b823e99f591e551ecdfc3315d97b203db | ||
|
|
||
| 上方向とした方向の処理をboolで管理していたけど、int directionで表す方法がある | ||
| これを使ってrowの更新を行う | ||
| https://github.com/fhiyo/leetcode/pull/58/commits/8689c74cda55693bdaaeca6721e9c80c9aaacf02#diff-9924eba75ce80cfb26b487ccdaaf7bae5d8affe8661b63382ef4051a602e81f6 | ||
| ## Discorなど | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| class Solution { | ||
| public: | ||
| string convert(string s, int numRows) { | ||
| if (numRows == 1) { | ||
| return s; | ||
| } | ||
| vector<vector<char>> transcription(numRows, vector<char>(s.size(), ' ')); | ||
|
|
||
| bool is_downforward = true; | ||
| int row = 0; | ||
| int col = 0; | ||
| for (int i = 0; i < s.size(); i++) { | ||
| transcription[row][col] = s[i]; | ||
|
|
||
| if (is_downforward) { | ||
| if (row == numRows - 1) { | ||
| is_downforward = false; | ||
| row--; | ||
| col++; | ||
| } else { | ||
| row++; | ||
| } | ||
| } else { | ||
| if (row == 0) { | ||
| is_downforward = true; | ||
| row++; | ||
| } else { | ||
| row--; | ||
| col++; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| string converted = ""; | ||
| for (int row = 0; row < transcription.size(); row++) { | ||
| for (int col = 0; col < transcription[0].size(); col++) { | ||
| if (transcription[row][col] == ' ') { | ||
| continue; | ||
| } | ||
| converted.push_back(transcription[row][col]); | ||
| } | ||
| } | ||
| return converted; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| class Solution { | ||
| public: | ||
| string convert(string s, int numRows) { | ||
| if (numRows == 1) { | ||
| return s; | ||
| } | ||
| // 文字が上から下に配置され、次に斜めに配置される部分を1セクションとする | ||
| // 上から下へはnumRows文字必要で下から上へ斜めにnumRows-2文字必要 | ||
| // 1セクションには合計numRows + (numRows - 2)文字が必要。 | ||
| // 必要なセクション数は、文字列の長さs.size()を(2*numRows - 2)で割った値。 | ||
| // 各セクションは、numRows - 1列が必要。 | ||
| int num_cols = ceil(s.size() / (2 * numRows - 2.0)) * (numRows - 1); | ||
| vector<vector<char>> transcription(numRows, vector<char>(num_cols, ' ')); | ||
|
|
||
| bool is_downforward = true; | ||
| int row = 0; | ||
| int col = 0; | ||
| for (int i = 0; i < s.size(); i++) { | ||
| transcription[row][col] = s[i]; | ||
|
|
||
| if (is_downforward) { | ||
| row++; | ||
| } else { | ||
| row--; | ||
| col++; | ||
| } | ||
|
|
||
| if (row == numRows - 1) { | ||
| is_downforward = false; | ||
| } | ||
| if (row == 0) { | ||
| is_downforward = true; | ||
| } | ||
| } | ||
|
|
||
| string converted = ""; | ||
| for (int row = 0; row < transcription.size(); row++) { | ||
| for (int col = 0; col < transcription[0].size(); col++) { | ||
| if (transcription[row][col] == ' ') { | ||
| continue; | ||
| } | ||
| converted.push_back(transcription[row][col]); | ||
| } | ||
| } | ||
| return converted; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| class Solution { | ||
| public: | ||
| string convert(string s, int numRows) { | ||
| if (numRows == 1) { | ||
| return s; | ||
| } | ||
| vector<string> string_per_row(numRows); | ||
|
|
||
| bool is_downforward = true; | ||
| int row = 0; | ||
| for (char letter : s) { | ||
| string_per_row[row] += letter; | ||
|
|
||
| if (is_downforward) { | ||
| row++; | ||
| } else { | ||
| row--; | ||
| } | ||
|
|
||
| if (row == numRows - 1) { | ||
| is_downforward = false; | ||
| } | ||
| if (row == 0) { | ||
| is_downforward = true; | ||
| } | ||
| } | ||
|
|
||
| string converted = ""; | ||
| converted.reserve(s.size()); | ||
| for (const auto& str : string_per_row) { | ||
| converted += str; | ||
| } | ||
| return converted; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| class Solution { | ||
| public: | ||
| string convert(string s, int numRows) { | ||
| if (numRows == 1) { | ||
| return s; | ||
| } | ||
| vector<string> string_per_row(numRows); | ||
|
|
||
| int direction = -1; | ||
| int row = 0; | ||
| for (char letter : s) { | ||
| string_per_row[row] += letter; | ||
|
|
||
| if (row == numRows - 1) { | ||
| direction = -1; | ||
| } | ||
| if (row == 0) { | ||
| direction = 1; | ||
| } | ||
| row += direction; | ||
| } | ||
|
|
||
| string converted = ""; | ||
| converted.reserve(s.size()); | ||
| for (const auto& str : string_per_row) { | ||
| converted += str; | ||
| } | ||
| return converted; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| class Solution { | ||
| public: | ||
| string convert(string s, int numRows) { | ||
| if (numRows == 1) { | ||
| return s; | ||
| } | ||
| vector<string> string_per_row(numRows); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 僕はシンプルにrowsとします |
||
|
|
||
| bool is_downforward = true; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. int direction = 1; // or -1
row += direction;というパターンもありです。 |
||
| int row = 0; | ||
| for (char letter : s) { | ||
| string_per_row[row] += letter; | ||
| if (is_downforward) { | ||
| row++; | ||
| } else { | ||
| row--; | ||
| } | ||
|
|
||
| if (row == numRows - 1) { | ||
| is_downforward = false; | ||
| } | ||
| if (row == 0) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. else ifとした方が僕は読みやすいと思いました
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @philip82148 |
||
| is_downforward = true; | ||
| } | ||
| } | ||
|
|
||
| string converted = ""; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. string conveted;で十分かつより効率的です(コンパイラの最適化でどっちも同じになりそうですが)。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. この部分ですが There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. C++ではオブジェクトは宣言と同時に初期化されます(コンストラクタが呼び出されます)よ C++のオブジェクトはいろんなコンストラクタ呼び出しの仕方があって、 // デフォルトコンストラクタ呼び出し
string str;
// 明示的に呼び出す
string str(5, 'a');
// 変換コンストラクタ
string str = "aiueo";
// これは以下と同じ
string str("aiueo");
// 初期化子リスト(initializer lists)
string str({'a', 'i', 'u', 'e', 'o'});
// 一様初期化
string str{5, 'a'};
string str{"aiueo"};
string str{'a', 'i', 'u', 'e', 'o'};
// なお変換コンストラクタは右辺を第一引数にしてコンストラクタ呼び出ししているだけなので、
// (コンストラクタ定義にexplicitというキーワードが付いていない限り)他でもできます
string str = {'a', 'i', 'u', 'e', 'o'};他にもコピーコンストラクタやムーブコンストラクタ等があります。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @philip82148 ありがとうございます。effective C++の19Pに組み込み型は初期化されない、vectorはいつでも保証されるのでこういった状況に対する良い方法はオブジェクトは使う前に必ず初期化する。と書かれておりました。 私は、この部分を組み込み型であってもなくてもオブジェクトは使う前に初期化しておけば安全と理解しておりました。 これは誤りかもしれませんので後ほどこの章を読み返してみます。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| converted.reserve(s.size()); | ||
| for (const auto& str : string_per_row) { | ||
| converted += str; | ||
| } | ||
| return converted; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. return reduce(string_per_row.begin(), string_per_row.end());でもいい(はず)です。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @philip82148 step4で使ってみました。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. それは確かにですね。そうなると return accumulate(string_per_row.begin(), string_per_row.end(), string());ともできます。 参考: |
||
| } | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Java や Python など文字列が immutable な言語では重要な話ですが、C++ では、mutable で後ろに文字をつける分には大きな問題になりません。
前後に付けたり分割したりなどする必要があるならば、Rope というデータ構造などを使えばいいですが、そこまでする必要があることは少ないです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
他言語のことをあまり意識できておりませんでした。
StringBuilderやjoinをレビュー時に見かけるのはこういった理由ですね。