戻り値

最終更新日03 Jul 2017 11:30

コピーコンストラクタと代入演算子のオーバーロードをした上でオブジェクト返しが正解(組み込み型以外)

参照返し Class& method() X
オブジェクト返し Class method() !…コピーコンストラクタと代入演算子のオーバーロードをしないとデータが消える
ポインタ返し Class* method() OK
  • 戻り値にconstをつけるべし

戻り値にconstをつける利点

演算結果に代入、なんてことを防ぐため。
privateなメンバ変数にユーザが悪さをするのを防ぐため。

戻り値を参照にすると?

  1. 関数内で宣言したローカル変数は返せない。
  2. クラスのプライベートメンバは返せるという利点。

2.は利点じゃなくて危険なことだから、やっちゃいけないのだ。
同様にしてメンバ変数をポインタとして返すのもだめだ。

オブジェクトな戻り値

オブジェクトを戻り値にすると、入力と出力ってかんじがしていいよね!

返り値がオブジェクトの時は、リファレンス返しにしない

存在しないオブジェクトのリファレンスを返そうとしてしまう場合があるからだ。
ベストな方法がこう

const CMiffy operator*(const CMiffy& _in){
 return CMiffy(x*_in.x,y*_in.y);
};

ただしoperator=だけはリファレンス返しにする!

代入演算子の書き方

String& String::operator=(const String& rhs){//right-hand-side
   if(this==&rhs){//ここでエラーチェック
     return *this;
   }
delete[] data;//古いメモリを削除して
data=new char[strlen(rhs.data)+1];//新しいメモリを割り当てる
strcpy(data,rhs.data);
return *this;
}
  1. 引数は(いつものように)constリファレンス渡しにする。
  2. 戻り値はオブジェクトのリファレンスにする1
  3. 戻り値にconstをつけない2
  4. return するのは*thisにすること3

関数の戻り値にconstを付ける意味

if(GetSomething(a)==c){}

を、
if(GetSomething(a)=c){}

という風に、ifに=を書いてしまう、というミスを防ぐことができるだってさ。戻り値をconstにしたからって、ifの=のミスがどうにかなるものか?コンパイルが通らなくなる、というメリットがあるってことか。

privateメンバ変数を守るため

戻り値がポインタの場合

constをつけると、reinterpret_castはできなくなる。

戻り値にconstをつけてはいけない例外

operator=ではconstをつけてはいけない。

疑問

イテレータを戻り値にしたいとき

const_iteratorを返すべき?
const ○○::iterator にするべき?

コンテナな戻り値

あたかもintとかの組み込み変数みたいに、なんの工夫もしなくてもそのままでイケる。

vector<string> testSTL()
{
  vector<string> sss;         // string 指定 vector オブジェクト
                               // sss は動的に拡張される
   vector<string>::iterator p; // 反復子
   string  s1;
   sss.push_back("hello ");       // コンテナにデータを追加
   sss.push_back("little ");
   sss.push_back(" \n");
   sss.push_back("ruby ");
   for( p = sss.begin(); p != sss.end() ; ++ p ) {
       cout << *p;
   }
   return sss;
}

エラー出力の時はヌルオブジェクトを生成して返す

戻り値をintもしくはenumにして、成功の時0,それ以外のエラー返しの時はエラーコードを示す0以外の数を返す、という手法もありますが、
私はエラーだったらエラー内容をprintfしてヌルオブジェクトを返す手法の方が好きです。
エラーがあってもとりあえずプログラムの実行を止めずにスルーできるから。


ファイル

サポートサイト Wikidot.com