3

Visual C++ 2013 では、const 参照に一時的な値を割り当てることは合法です。たとえば、

const int& a = 1;

大規模なソフトウェア プロジェクトで、実行に約 10 ミリ秒かかる 1 行のコードに出くわしました。

const std::vector<Item>& desc = (hasItems) ? instance->getItems() : std::vector<Item>();

Itemは約 20 バイトの構造体で、instance->getItems()はconst std::vector< Item>&を返します 。この行の実行に 1 秒以上の時間がかかる理由がわかりませんでした。

const std::vector<Item>& desc = std::vector<Item>();

も 10 ミリ秒かかりますが、

std::vector<Item> items;
const std::vector<Item>& desc = items;

ご想像のとおり、0.00.. ms というほぼ瞬時です。

問題は、既存の複雑なソフトウェア プロジェクトでこの問題を確実に再現できることですが、凝縮された最小限の例では、両方のバージョンが同じように高速に実行されます。最適化を有効にしたリリース ビルドでこれらすべてをテストしました。これらの最適化のいずれかによって、この例外が const 参照への値の代入が非常に遅くなる可能性はありますか? この動作の原因を知りたいです。誰がこれを引き起こしているのか手がかりを持っていますか?

フォローアップとして、誤って無効にした const 参照に値を割り当てることに対する警告はありますか? もしそうなら、そのIDは何ですか?これが発生するコード内の他の場所をコンパイラが指摘できれば便利です。

編集: タイミングは、対象のコードの直前と直後の単純な CPU クロックを 1 秒あたりのクロック サイクルで割った値で行われました。あまり正確ではありませんが、10.something と 0.something の違いの一般的なアイデアを提供します。この特定の例では完全に再現可能です。実行時間に大きな違いがあります。

4

1 に答える 1

2
const std::vector<Item>& desc =
      (hasItems) ? instance->getItems() : std::vector<Item>();

予想外かもしれませんが、この行は の戻り値がgetItems参照するベクトルのコピーを作成します。

正式には、条件演算子によって実行される型強制のルールは、そうするために共謀します。実際には、コンパイラには選択の余地がありません。参照が一時オブジェクトにバインドされている場合、参照が最終的にスコープ外になったときに、コンパイラはその一時オブジェクトを破棄するコードを生成する必要があります。一時的に、時には左辺値に。この状況を回避するために、型強制のルールが記述され、条件の両方の分岐で一時的なものが確実に作成されるようにします。

このようなものが役立つはずです:

std::vector<Item> blank;
const std::vector<Item>& desc =
      (hasItems) ? instance->getItems() : blank;

または、getItems()アイテムがない場合に有効な空のベクターへの参照を返すように設計し、呼び出し元がフープをジャンプする必要がないようにすることもできます。その目的のために静的な常に空のベクトル変数を保持することは不合理ではありません。

于 2016-07-08T14:41:02.767 に答える