web-dev-qa-db-ja.com

ベクトルはすべての負の値をゼロに変換しました

負の値を格納するために一定サイズのベクトルを作成し、取得した値をすべてゼロで出力しました。なぜ負の値を保存しないのか知りたいだけです。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v(5);
    v.Push_back(-1);
    v.Push_back(-2);
    v.Push_back(-3);
    v.Push_back(-4);
    v.Push_back(-5);

    for (int i=0; i<5; i++)
       std::cout << v[i] << " ";  // All I got was zeroes
}
31
Suhail Akhtar

これは、Push_backがベクターの最後にnew要素を置くためです。

iから9を実行すると、効果を確認できます。負の数はv[5]からv[9]を占有します。

書き込み

std::vector<int> v{-1, -2, -3, -4, -5};

代わりに、特にエレガントな修正プログラムです。

53
Bathsheba

呼び出すコンストラクターは、最初の5つの要素をゼロで埋めます。 here (オーバーロードのリストの#3)を参照してください。

Tのデフォルトで挿入されたインスタンスをcount個持つコンテナを構築します

intの「デフォルトで挿入されたインスタンス」は0です)。あなたが望んでいたかもしれないものは

std::vector<int> v;

v.reserve(5); /* Prevent unnecessary allocations as you know the desired size. */

v.Push_back(-1);
/* ... */

元のコンストラクター呼び出しを使用する代替手段は

#include <numeric>

std::vector<int> v(5);

std::iota(v.rbegin(), v.rend(), -v.size());

ただし、すべての要素が最初にデフォルトで構築されてから新しい値に再度割り当てられるため、これは必要以上に多くの作業を行います。

25
lubgr

これは、 DRY原則 が間違いの理解に役立つ場合です。

vector<int> v(5);

...

for(int i=0;i<5;i++)

ここでは、5つの要素用にスペースを確保すると思われる配列を作成しています。次に、これらの5つの要素を挿入します。その後、配列全体の内容を印刷したかったのですが、単にv.size()と書く代わりに、5。これにより、コードは「vのすべての要素を印刷」ではなく、「vの最初の5つの要素を印刷」のようになります。

代わりにあなたが意味することを書いたなら、あなたは配列が実際に5ではなく10の要素を持っていることがわかるでしょう。

ところで、C++ 11以降では、すべての要素をより簡単な方法でループオーバーできます。

for(int x : v)

または、要素がよりコピーコストの高いタイプである場合、auto- type参照であっても、要素への参照を使用できます。

for(auto& x : v)

この新しいfor- loop構文は、 範囲ベースのfor loop と呼ばれます。

12
Ruslan

vectorは、C/C++のプリミティブ配列の柔軟なバージョンと考えることができます。 vectorをサイズnで初期化すると、構築されたvectorのサイズはnのサイズになります(またはメモリ内で大きくなる場合がありますが、コンパイラによって暗黙的に処理されるため、知っている)。ここでnはエントリの数を表しますが、実際のメモリ使用量(つまりバイト数)ではありません。サイズパラメーターで初期化しない場合、vectorはサイズ0で空になりますが、メモリー内では暗黙的なデフォルトのメモリーサイズになります。

現在のvectorのサイズが5であるとします。そして、別の要素でPush_back()したい場合、vectorは内部的に配列全体を新しいメモリ位置に再割り当てします。古いエントリと新しいエントリをすべて保持します。したがって、Cでやらなければならないように、メモリを自分で手動で再割り当てする必要はありません。

ここで、あなたの例では、vectorにこれらの5つの負の整数を入力するために、いくつかの方法があります。

1)サイズを指定せずにvectorを初期化できます。次に、必要な各要素をプッシュします。

vector<int> v;
for (int i = -1; i >= -5; --i) {
    v.Push_back(i);
}

2)そのサイズパラメータを使用して、vectorを初期化できます。そして、それらに新しい値を割り当てます。

vector<int> v(5);
for (int i = 0; i < v.size(); ++i) {
    v[i] = -i;
}

3)構築時にvectorをこれらのエントリで初期化することもできます。

    vector<int> v{-1, -2, -3, -4, -5};
or  vector<int> v = {-1, -2, -3, -4, -5};
5
hiimdaosui

でベクトルを宣言したとき

std::vector<int> v(5);

vに5つの4バイトスペースをメモリに格納し(システムでint = 4バイトと仮定)、デフォルトでこれらの4バイトスペースはすべて0を表すビットを格納します。次に、さらに5つの整数(-1、-2、-3、-4、-5)をベクターの最後にプッシュしました:

v.Push_back(-1);
v.Push_back(-2);
v.Push_back(-3);
v.Push_back(-4);
v.Push_back(-5);

この時点で、ベクトルには10個の要素があります。最初の5個は、プログラムを実行したインスタンスに0を格納する不明な整数です。 forループはベクトルの最初の5つの要素を出力するため、これがすべて0を出力する理由です。

0