- - PR -
return文にあるstringについて
1
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-09-09 04:48
いつもお世話になっております。
(環境 VS2005を使用VC++の質問) 現在のソースコードに以下のようなセンテンスがあります。 CString sTest(GetColumnName(CommandID1).c_std()); 以下メンバ関数 std::string test::GetColumnName(int commandID) { switch(commandID) { Case '1' return "なにか1"; Case '2' return "なにか 2"; } } この文ですと、文字列をそのまま返しているため、変数を作って返すとします。 std::string test::GetColumnName(int commandID) { std::string s; switch(commandID) { Case '1' s = "なにか1"; return s; Case '2' s = "なにか 2"; return s; } } 上記のような状態でコンパイル実行上、とくに問題は起きません。が、どうも腑に落ちません。 実際実行上でも問題はなかったです。ですが、以下が通常やる場合の文字列返しパターンかとも思います。。 void test::GetColumnName(int commandID, std::string& s) { switch(commandID) { Case '1' s = "なにか1"; break; Case '2' s = "なにか 2"; break; } } 実際1番目でも2番目でもできるのですが、1番目がどうも腑に落ちないため質問させていただきました。 感覚としてこれではだめなんじゃないかということなのですが、特にスコープの問題も起きずに実行できました。 これは、どちらでもよいのでしょうか?それとも2番目のやり方が正しい方法なのでしょうか? 知っている上では局所的に変数を作った場合(この場合std::string s)それを返してはいけないはずなのですが、この場合問題は起きませんでした。 それがわかっているため、腑に落ちないのですが。。。 以上初心者レベルかもしれない質問になります。 どうかよろしくお願いします。 | ||||||||||||||||
|
投稿日時: 2008-09-09 07:38
私の適当な理解で書きます。
正しい知識は言語仕様を見て身につけて下さい。 また、仕様に詳しい方、説明でまずい点があればご指摘をお願いします。
return文でstd::string("なにか1");が実行され、この内容が返されます。 (コピーコンストラクタが走るかどうかは覚えていません)
return文でstd::stringのコピーコンストラクタが走ります。
最適化によって差を埋めてくれることもありますが、return s;とした場合に実際にコピーが走るコードが残る可能性もあります。 従って、std::string&の引数で処理した方がコストが少ない可能性があるのかもしれません。
よく「だめ」と言われるのは、ローカル変数のポインタを返すことです。 int* Func() { int a = 5; return &a; } このような場合、aの位置は関数を抜けた時点で使われなくなり、期待した値にならない可能性があります。 | ||||||||||||||||
|
投稿日時: 2008-09-09 07:41
あとはcommandIDが想定外の値だった場合の対応ですね。
空文字列を返すのであれば、std::stringが戻り値でも構わないかもしれませんが、成否(true/false)やエラーコード(intとか?)を戻り値として返したい場合は、関数の戻り値を成否やエラーコードの型で、成功時の戻り値を引数でということも考えられます。 | ||||||||||||||||
|
投稿日時: 2008-09-09 07:47
おはようございます。
1番目は、いわゆる「(型)変換コンストラクタ」が働き、暗黙の型変換がおこなわれています。 2番目は、ローカル変数を返す際に「コピーコンストラクタ」によって、コピーされています。 私的には… 2番目では、文字列を返すために2度コンストラクタを呼び出さないといけないオーバーヘッドを嫌い できるだけ避けたいですね。 つまり、1番目のほうがよいと思います。 | ||||||||||||||||
|
投稿日時: 2008-09-09 21:40
そもそも、コンパイルが通らないと思います。
VC++8 では、デフォルトで UNICODE 指定です。CString は、「typedef ATL::CStringT< TCHAR, StrTraitMFC< TCHAR > > CString;」と、定義されていると思います。このため、Unicode 文字列を期待するようにプリコンパイルされます。std::string とは、文字コードが異なります。
「感覚として」ということなので「1番目がどうも腑に落ちない」については突っ込みません。しかし、その後の「特にスコープの問題も起きずに」とのつながりがわかりませんでした。これによって、「1番目って、メソッド内で s を宣言しているコードのこと?」と、混乱しました。 | ||||||||||||||||
|
投稿日時: 2008-09-09 22:28
私は C++ はあまり知らないので直接的な回答はできませんが、こういうのはデバッガーでステップ実行させてみると分かりやすいです。コード上ではあらわに見えない暗黙のコンストラクターなども通ることが分かると思います。 |
1