2011-09-22 10 views
7

C++標準では、期待される機能を実際に妨げる可能性がある点まで最適化が可能であることを読んだことがあります。私がこれを言うとき、私は戻り値の最適化について話しています。ここでは、コピーコンストラクタに実際にロジックがあるかもしれませんが、コンパイラは呼び出しを最適化します。C++での最適化に関する質問

これは、これを知らない人がこれに起因するバグを修正するのにかなり時間を費やす可能性があるため、やや悪いことがわかります。

私が知りたいことは、コンパイラの過度の最適化が機能を変更できる他の状況があるかどうかです。

int x = 1; 
x = 1; 
x = 1; 
x = 1; 

= 1つのXに最適化されるかもしれません。たとえば、のようなものが

私が持っていると仮定します。これは、おそらくも

class A; 

A a = b; 
a = b; 
a = b; 

を最適化していませんか?おそらくない最良の例が、私はは、コンパイラが副作用が目に見えてを変更する場所のポイントに最適化することが許可されている場合のみです...あなたは私が何を意味するか知って

+4

私は近い票に同意しません。これは本当の、答えられる質問です。 –

+4

コピーctorを削除すると、コードのバグが発生し、最初にコピーctorを間違って設計しました。コードは、オブジェクトの数やオブジェクトのコピー/割り当ての頻度に依存してはいけません。 – PlasmaHH

+1

コピーctorのロジックは、オブジェクトをコピーするロジックにする必要があります。それがコピーされない場合、なぜctorロジックをコピーする必要がありますか? –

答えて

12

Elidingコピー操作を願っています。コピーコンストラクタが呼び出されることに頼らないで、コンパイラはそれらの呼び出しを最適化するかもしれません。

他のすべてについては、「as-if」ルールが適用されます。可視副作用がコンパイラがまったく最適化していない場合と同じである限り、コンパイラは最適化します。

(「可視副作用」は、コンソールやファイルシステムに書き込まれ、例えば、ものを含むが、ファン速度をランタイムとCPUではない。)

+0

+1:「副作用が目立つように変わります。目に見える副作用が実際にどのようなものかを考えてみる価値があります。 –

+1

これはr値が導入される前のことでした。これにより、最適化が可能になりました。 r値が存在するので、それらの最適化はおそらく関連性がありません(コピーエリッションは移動コンストラクタの呼び出しよりも速いが、同じマージンではない)が、後方互換性のためではなく保存されています。とにかくトリックのためにコピーコンストラクタを使用しないことを人々は学んだことがあります。 –

+0

@Rob:それはあなたの味のために十分でしょうか?) – sbi

1

これはコンパイラかどうか、class Aがどのように実装されるかに依存します実装がわかり、それが十分にスマートであるかどうかを確認できます。たとえば、class Aoperator=()にいくつかの副作用がある場合、最適化するとプログラムの動作が変わる可能性があります。

3

最適化されている可能性があります。しかし、あなたはまだ例えば、仮定するコード、プロセスをある程度制御することがあります。

 
    int x = 1; 
    x = 1; 
    x = 1; 
    x = 1; 
    volatile int y = 1; 
010B1004 xor   eax,eax 
010B1006 inc   eax 
010B1007 mov   dword ptr [y],eax 
    y = 1; 
010B100A mov   dword ptr [y],eax 
    y = 1; 
010B100D mov   dword ptr [y],eax 
    y = 1; 
010B1010 mov   dword ptr [y],eax 

つまり:

int x = 1; 
x = 1; 
x = 1; 
x = 1; 
volatile int y = 1; 
y = 1; 
y = 1; 
y = 1; 

どちらのx、またyはこのフラグメントの下に使用されていると仮定すると、VS 2010は、コード生成します最適化はすべての行を "x"で取り除き、4行すべてに "y"を残します。これはどのようにvolatileが動作するのですが、どのコンパイラがあなたのために何を制御するかということが重要です。

クラス、またはプリミティブ型のいずれであっても、すべてコンパイラに依存しますが、最適化の上限はどの程度洗練されていますか。研究のため

別のコードフラグメント:何も

class A 
{ 
private: 
    int c; 

public: 
    A(int b) 
    { 
     *this = b; 
    } 
    A& operator = (int b) 
    { 
     c = b; 
     return *this; 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int b = 0; 
    A a = b; 
    a = b; 
    a = b; 
    return 0; 
} 

のVisual Studio 2010の最適化ストリップすべてのコード、「完全な最適化」_tmainでビルドのリリースでは、ただ何もしないし、すぐにゼロを返します。

-1

私はそのくらいのC++を知らないが、現在はコンパイラ-原則を読んでいます、ここでは技術やツール

は、コードの最適化にそのセクションからの抜粋です:

機種に依存しないコード最適化フェーズ 中間コードを改善して、より良いターゲットコードが得られるようにします。通常 はより速いことを意味しますが、 短いコードや消費電力の少ないターゲットコードなど、他の目的が望まれる場合があります。例えば、 直接アルゴリズムは、 を使用して、意味解析器からの というツリー表現の各演算子に対する命令を使用して中間コード(1.3)を生成する。単純な中間コード生成 アルゴリズムの後にコード最適化を行うと、 が適切なターゲットコードを生成するための合理的な方法になります。 optimizerは、 整数から浮動小数点への変換を1回、 をコンパイル時にすべて行うことができるので、浮動小数点数60.0で整数6-を置き換えることで、intfofloat演算を除去することができます。 さらにt3はそう オプティマイザはより短い配列(1.4)

1.3 
t1 - intoffloat(60 
t2 -- id3 * id1 
ts -- id2 + t2 
id1 t3 

1.4 
t1=id3 * 60.0 
id1 = id2 + t1 

すべてに1.3を変換することができID1にその値をtrasmitするために、一度だけ使用され、私が意味するすべては、そのコードの最適化がでてくるはずですと言ってコードがそうした単純な状態になっているため、コードが実行する効果に影響しません。

0

最適化では、「コピーまたは割り当ての呼び出しを削除しません」。 有限状態機械を、同じ外部動作を持つ別の有限状態機械に変換します。

は今、あなたはrepeadlyコンパイラは何をすべきか

a=b; a=b; a=b; 

を呼び出す場合、実際に何であるかoperator=に依存します。 コールがプログラムの状態を変更する機会を持たないことがコンパイラによって判明した場合(および「プログラムの状態」が「スコープがアクセスできるスコープよりも長持ち」であること)、それは除去されます。 これを「実証」することができない場合、通話はそのまま維持されます。

コンパイラが何をするにしても、あまり心配する必要はありません。コンパイラは、(契約によって)プログラムまたはその一部の外部ロジックを変更することはできません。

-1

私はconst変数とconst_castでいくつか問題がありました。コンパイラは、何か他の計算に使用されたときに不正確な結果を生成しました。 const変数は最適化され、古い値はコンパイル時定数になりました。本当に "予期しない動作"。さて、おそらくない;)

例:

const int x = 2; 
const_cast<int&>(x) = 3; 
int y = x * 2; 
cout << y << endl; 
+0

これについては何も予想外です。 'const_cast'は、' const'宣言されていないオブジェクト(例えば、悪いAPIを扱うときや、 'operator'呼び出しのペアを定義するショートカットをとるときなど)を参照するためのものです。対照的に、Standardは、もともと 'const'と宣言された変数の' const'nessをキャストすることは未定義の振る舞いであると非常に意図的に述べています。 –