いつもお世話になっております
下記のような記述をした場合
MYCLASS operatir+(MYCLASS &a, MYCLASS &b){
MYCLASS ret;
・・・・ // a + b を処理し ret に格納
return ret
}
return ret のところで
ret のコピー(テンポラリオブジェクト?)が作成され
( MYCLASS(MYCLASS &x) で定義されたコンストラクタが走ります)
コピーが返値として 返ります
ここで コピー を作成するのは無駄なので
いずれ 返値になるであろう テンポラリオブジェクト を先に生成し
a + b の結果を格納して 返してやる方法はないでしょうか
MYCLASS& operatir+(MYCLASS &a, MYCLASS &b){
MYCLASS *ret = new MYCLASS();
・・・
return *ret;
}
だと コピーは作成されませんが
どこかのタイミングで delete が必要になるんですよね〜
MYCLASS a, b, c;
a = b + c;
とかやったら どこを delete してよいものやら・・・
operator だね
つづり間違えてる・・・
はずかし
余分な部分もありますが、下記コードで下のように入れ替えを行った際の
"copy constructor"等の出力数を数えてみて下さい。
・operator +()の実装:(1)と(2)を入れ替える
・返り値の受けてのインスタンス生成方法:(3)と(4)を入れ替える
class A {
private:
int num;
public:
A(int n = 0) : num(n) { cout << "not copy constructor" << endl; }
A(const A& a) : num(a.num) { cout << "copy constructor" << endl; }
A& operator =(const A& r) {
num = r.num;
cout << "operator =" << endl;
return *this;
}
int get() const { return num; }
};
A operator +(const A& op1, const A& op2) { return A(op1.get() + op2.get()); } // (1)
A operator +(const A& op1, const A& op2) {
A result(op1.get() + op2.get());
return result;
} // (2)
int main(int argc, char **argv) {
A a1(5), a2(8);
A a3(a1 + a2); // (3)
A a3 = a1 + a2; // (4)
cout << a3.get() << endl;
a3 = a1;
cout << a3.get() << endl;
}
書き忘れました。こちらは、
OS:HP-UX,コンパイラ:aCC
で実験しましたが、それぞれの入れ替えで効果がありました。
コンパイラの実装依存の話かと思いますが、どのコンパイラも返り値最適化程度は
行っているのではないかと。
わたしの 環境は
Windows2000, VC6SP5 です
(1)-(3)
not copy constructor
not copy constructor
not copy constructor
13
operator =
5
(1)-(4)
not copy constructor
not copy constructor
not copy constructor
13
operator =
5
(2)-(3)
not copy constructor
not copy constructor
not copy constructor
copy constructor
13
operator =
5
(2)-(4)
not copy constructor
not copy constructor
not copy constructor
copy constructor
13
operator =
5
上記のような結果になりました
return MYCLASS();
のように 記述すると コピーを作成しないようですね
でも
return MYCLASS(a.member + b.member);
のような 簡単な + 演算なら この記述でいけるのですが
もっと複雑な(実は 多倍長演算のライブラリ作ろうと思って)場合
MYCLASS( の中に 記述しきれませんよね・・・
やはり ワーク変数 result をそのまま返値としたいです
いい方法ないでしょうか
More Effective C++の第20項とか,
Efficient C++の第4章を参照してみて下さい。
RVOを利用できるか否かは,コンパイラに依存します。
基本的には「できたらもうけもの」程度の意識でいるのがよいと思います。
RVO(Return Value Optimization) ですか>ちょっと調べてみました
その中でも 今回やりたいことは
NRVO (Named Return Value Optimization)
と呼ばれるものみたいですね
VC++ のコンパイラでは RVO までしかサポートしていない模様でした
ま 最悪
MYCLASS(MYCLASS &a, MYCLASS &b, int flg)
のような コンストラクタを作成し
すべての 演算を コンストラクタ内で行う という手を いま思いつきました
これで コピーコンストラクタ は走らなくなりますが
記述が大変だ・・・
Efficient C++ って有名な 書籍みたいですね
3,500円か〜
近所のパソショップに置いてあったら一読してみようと思います
以上 ありがとうございました
ツイート | ![]() |