как строится вектор объектов (со статическими элементами) - PullRequest
0 голосов
/ 19 октября 2011

Я написал следующий код для проверки вектора объектов, имеющих статический член.Я ожидаю, что результат будет:

1 2 3 4 5
6 7 8 9 10

Но фактический вывод:

1 2 3 4 5
6 6 6 6 6

Похоже, что статический элемент не увеличен, как ожидалось.Кто-нибудь может объяснить это?

// ==== test.h =====
using namespace std;

void test();

class Record{
    static int total_number;
    int id;
public: 
    Record();
    void show() {std::cout << id << " "; }
};


// ==== test.cpp ====
#include "stdafx.h"
#include <iostream>
#include <vector>
#include "test.h"
using namespace std;

Record::Record(){
    total_number += 1;
    id = total_number;
 }

void test(){

    const int vec_length = 5;
    Record a[vec_length];

    for (unsigned int i=0; i<vec_length; i++)
        a[i].show();

    cout << endl;    

    vector<Record> vr(vec_length);
    for (unsigned int i=0; i<vr.size(); i++)
        vr[i].show();
    cout << endl;
}


// ==== main.cpp =====
#include "stdafx.h"
#include <iostream>
#include "test.h"
using namespace std;

int Record::total_number = 0;

int _tmain(int argc, _TCHAR* argv[])
{
    test();
    return 0;
}

Ответы [ 5 ]

3 голосов
/ 19 октября 2011

В C ++ 98/03 ваш вектор инициализируется этим конструктором:

std::vector<Record> v(5, Record());

Это создает один новый объект, увеличивающий статическую переменную, а затем делает пять копий этой переменной для заполнения элементов. Всего по умолчанию одна и пять копирующих конструкций, что дает 6 6 6 6 6

В C ++ 11 конструктор:

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

Это создает пространство для пяти элементов и инициализирует их значением, что для вашего типа означает, что конструктор по умолчанию вызывается один раз для каждого элемента. Всего пять конструкций по умолчанию, что дает 6 7 8 9 10.

2 голосов
/ 19 октября 2011

Полагаю, ваше определение Record::Record выглядит следующим образом

Record::Record() : id(++total_number) {}

и вы ожидаете, что конструктор vector<Record> вызовет именно этот конструктор. Однако vector делает это только один раз и копирует остальное с помощью сгенерированного компилятором конструктора копирования, который будет выглядеть примерно так:

Record::Record(const Record &other) : id(other.id) {}

Вам тоже придется это перезаписать.

1 голос
/ 19 октября 2011

Определение используемого вами векторного конструктора:

явный вектор (size_type n, const T & value = T (), const Allocator & = Allocator ()); Конструктор повторяющихся последовательностей: Инициализирует вектор с его содержимым, установленным для повторения, n раз, копий значения. Вот ссылка на справочную страницу

Полагаю, это означает, что векторный конструктор будет запускать ваш конструктор по умолчанию один раз (в результате 6), а затем ваш конструктор копирования еще 4 раза (в результате - больше 6).

1 голос
/ 19 октября 2011

Я бы предложил (и в отсутствие полного кода я предполагаю, что в Record :: Record () вы делаете ++ total_number), что проблема здесь

vector vr (vec_length);

, который инициализирует std :: vector с записью vec_length.

std :: vector требует, чтобы его типы были копируемыми, то есть вы должны реализовать Record :: Record (const Record &).Вот что происходит: так как std :: vector не имеет Record (), он создает его, создавая его (вызывается Record :: Record (), что увеличивает общее количество до 6).Затем остальные записи vec_length-1 копируются путем вызова Record :: Record (const Record &) с только что созданным экземпляром.

Поскольку вы не указали copy-ctor, компилятор создал для вас такую, котораяпросто делает побитовую копию объекта.Поскольку vec_length является статическим для класса, ничего копировать не нужно - но также и потому, что copy-ctor не увеличивает статическое, ничего не происходит (т. Е. Значение просто сохраняется).

Таким образом, вывод для них6.

1 голос
/ 19 октября 2011

Как vector<Record> vr(vec_length); несколько слабоват.Я предполагаю, что вы ожидаете vec_length вызовов конструирования по умолчанию, но другой жизнеспособной реализацией является создание одного построенного объекта по умолчанию, за которым следуют vec_length-1 копии.Тем не менее, вы не смогли предоставить подходящий конструктор копирования.

...