1


1

構造体要素を含むstd :: vectorのサイズ

構造体要素を使用して適切なサイズのベクトルを取得するのが困難です。 要素クラスは次のように定義されます(関連する唯一の事実はintと2つのdoubleを含むクラスだと思いますが、詳細は省略しませんでした)。

class Interval
{
public:
    Interval(int _i = 0, scalar _l = 0, scalar _r = 0) :
        index(_i),
        l(_l),
        r(_r)
    { }

    inline double left(void)    const { return l; }
    inline double right(void)   const { return r; }

    inline bool operator < (const Interval & i2) const { return left() < i2.left(); }

public:
    int index;
    double l;
    double r;

};

次に、関数にこのコードがあります:

std::vector arr(10);
int s1 = arr.size();
int s2 = arr.end() - arr.begin();

取得するs1の値は15ですが、s2は正しい値10です。 何が起こっている? size()は要素の数を正確に返すことを想定していませんか? それはarr.end()-arr.begin()と同じではないでしょうか?

どんな回答やコメントも歓迎します。

4 Answer


1


最初に、コードをフォーマットするときにHTMLタグの使用を停止します。 代わりに[コード]ボタンを使用してください。

第二に、あなたが説明するのは、説明に反するミステリーです。 s1`と s2`の両方で同じ値( 10)を取得する必要があります。 それは、何らかの形で他のコードでベクターの整合性をなんとかして破壊しない限りです(つまり、 実行するコードは、表示されるコードではありません)。


1


Codepadで期待どおりに動作します


0


*編集:*より多くの情報を提供したので、おそらくこの混乱する動作に光を当てることができます。

One Definition Ruleに違反しています。 これを実行した結果は実際には定義されていませんが、観測結果に基づいていくつかの経験に基づいた推測を行うことができます。

これはテンプレートパラメータの置換に必要なので、テンプレート関数は常にインラインで宣言されます。 コンパイラは、これらの関数のいずれかを検出すると、インラインコードとして出力するか、関数本体を作成して呼び出すかを選択できます。 関数本体を作成する場合、リンカは異なる翻訳単位で重複する定義を削除する責任を負います。 リンカは、見かけの重複が機能的に同等であるかどうかを確認するために多くのチェックを行いません。引数の型に依存する、関数の装飾名を使用します。タイプの名前がす​​べて同じ場合、それらは同一であると見なされます。 One Definition Ruleにより、この仮定を立てることができます。

これにより、ソースに含まれていないクラス定義がコードの結果に影響を与えることができます。リンカは、コードの悪いコピーを良いコードに置き換えています。 コンパイラがインラインコードを生成する場合、期待する結果が得られます。リンカーが関与する場合、50/50の確率で間違ったものが取得されます。 そして、たとえあなたのコードが幸運になっても、他のコードの一部は今や強打されています。

'' '' '

元の答え:ベクトルが要求されたサイズより大きくなることは可能ですが、 size`はその値を反映しません。 http://www.cplusplus.com/reference/stl/vector/capacity/ [`capacity]を使用してこれをテストできます。 余分なストレージはメモリ使用量の一部になりますが、要素は初期化されず、「サイズ」の結果を超えてアクセスしようとすると、未定義の動作になります。