Stackoverflow(https://stackoverflow.com/)は、おそらくこの質問のためのより良いディスカッションフォーラムです。しかし、ここに短い答えがあります。
上で説明したように、C ++コンパイラがこの式のコードを生成しているとは思いません。最新のC ++コンパイラーはすべて、「戻り値の最適化」と呼ばれる最適化を実装しています(http://en.wikipedia.org/wiki/Return_value_optimization)。戻り値を最適化すると、の結果evolutionMatrix*stateMatrix
はに直接格納されstateMatrix
ます。コピーは作成されません。
このトピックには明らかにかなりの混乱があり、それがStackoverflowの方が優れたフォーラムになる可能性があると私が提案した理由の1つです。そこには多くのC ++の「言語弁護士」がいますが、ここで私たちのほとんどはCSEに時間を費やしたいと思っています。;-)
バンガース教授の投稿に基づいて、次の簡単な例を作成しました。
#ifndef NDEBUG
#include <iostream>
using namespace std;
#endif
class ExpensiveObject {
public:
ExpensiveObject () {
#ifndef NDEBUG
cout << "ExpensiveObject constructor called." << endl;
#endif
v = 0;
}
ExpensiveObject (int i) {
#ifndef NDEBUG
cout << "ExpensiveObject constructor(int) called." << endl;
#endif
v = i;
}
ExpensiveObject (const ExpensiveObject &a) {
v = a.v;
#ifndef NDEBUG
cout << "ExpensiveObject copy constructor called." << endl;
#endif
}
~ExpensiveObject() {
#ifndef NDEBUG
cout << "ExpensiveObject destructor called." << endl;
#endif
}
ExpensiveObject operator=(const ExpensiveObject &a) {
#ifndef NDEBUG
cout << "ExpensiveObject assignment operator called." << endl;
#endif
if (this != &a) {
return ExpensiveObject (a);
}
}
void print() const {
#ifndef NDEBUG
cout << "v=" << v << endl;
#endif
}
int getV() const {
return v;
}
private:
int v;
};
ExpensiveObject operator+(const ExpensiveObject &a1, const ExpensiveObject &a2) {
#ifndef NDEBUG
cout << "ExpensiveObject operator+ called." << endl;
#endif
return ExpensiveObject (a1.getV() + a2.getV());
}
int main()
{
ExpensiveObject a(2), b(3);
ExpensiveObject c = a + b;
#ifndef NDEBUG
c.print();
#endif
}
最適化モードでコンパイルするときに、出力を出力するためのすべてのコードを完全に削除したかったため、実際よりも複雑に見えます。デバッグオプションでコンパイルしたバージョンを実行すると、次の出力が表示されます。
ExpensiveObject constructor(int) called.
ExpensiveObject constructor(int) called.
ExpensiveObject operator+ called.
ExpensiveObject constructor(int) called.
v=5
ExpensiveObject destructor called.
ExpensiveObject destructor called.
ExpensiveObject destructor called.
通知に最初のものは、ということです何の一時のみ、B、およびCをconstructed--されていません。デフォルトのコンストラクターと代入演算子は、この例では必要ないため、呼び出されることはありません。
バンガース教授は表現テンプレートについて言及しました。確かに、この最適化手法は、マトリックスクラスライブラリで良好なパフォーマンスを得るために非常に重要です。ただし、オブジェクト式が単にa + bよりも複雑な場合にのみ重要です。たとえば、私のテストが代わりだった場合:
ExpensiveObject a(2), b(3), c(9);
ExpensiveObject d = a + b + c;
次の出力が得られます。
ExpensiveObject constructor(int) called.
ExpensiveObject constructor(int) called.
ExpensiveObject constructor(int) called.
ExpensiveObject operator+ called.
ExpensiveObject constructor(int) called.
ExpensiveObject operator+ called.
ExpensiveObject constructor(int) called.
ExpensiveObject destructor called.
v=14
ExpensiveObject destructor called.
ExpensiveObject destructor called.
ExpensiveObject destructor called.
ExpensiveObject destructor called.
このケースは、一時的な構成(コンストラクターへの5つの呼び出しと演算子+の2つの呼び出し)の望ましくない構成を示しています。式テンプレート(このフォーラムの範囲をはるかに超えるトピック)の適切な使用は、これを一時的に防止します。(非常にやる気のある人のために、式テンプレートの特に読みやすい議論はhttp://www.amazon.com/C-Templates-The-Complete-Guide/dp/0201734842の第18章にあります)。
最後に、コンパイラが実際に行っていることの実際の「証明」は、コンパイラによって出力されたアセンブリコードを調べることから得られます。最初の例では、最適化モードでコンパイルした場合、このコードは驚くほど単純です。すべての関数呼び出しは最適化され、アセンブリコードは基本的に2を1つのレジスタに、3を1つのレジスタにロードし、それらを追加します。