2009-05-11 3 views
2

Я пытаюсь создать массив объектов класса, принимающих целочисленный аргумент. Я не вижу, что не так с этим простым маленьким кодом. Может ли кто-нибудь помочь?Нужна помощь в создании массива объектов

#include <fstream> 
#include <iostream> 
using namespace std; 

typedef class Object 
{ 
int var; 
public: 
Object(const int& varin) : var(varin) {} 
} Object; 

int main (int argc, char * const argv[]) 
{ 
for(int i = 0; i < 10; i++) 
{ 
    Object o(i)[100]; 
} 

return 0; 
} 

ответ

8

В C++ вам не нужно typedef с для class эсов и struct с. Итак:

class Object 
{ 
int var; 
public: 
Object(const int& varin) : var(varin) {} 
}; 

Кроме того, описательные имена всегда preferrable, Object много ругали.

int main (int argc, char * const argv[]) 
{ 
int var = 1; 

Object obj_array[10]; // would work if Object has a trivial ctor 

return 0; 
} 

В противном случае, в вашем случае:

int main (int argc, char * const argv[]) 
{ 
int var = 1; 

Object init(var); 
Object obj_array[10] = { var, ..., var }; // initialize manually 

return 0; 
} 

Хотя, на самом деле вы должны искать vector

#include <vector> 
int main (int argc, char * const argv[]) 
{ 
int var = 1; 

vector<Object> obj_vector(10, var); // initialize 10 objects with var value 

return 0; 
} 
4

dirkgently-х изношенном достаточно точное представление массивов элементов в C++, но где он инициализирует все элементы массива с одинаковым значением, похоже, что вы пытаетесь инициализировать каждый с отдельным значением.

Чтобы ответить на ваш вопрос, создайте массив объектов, которые принимают параметр конструктора int. Вы не можете, объекты создаются при распределении массива и при отсутствии тривиального конструктора, который ваш компилятор будет жаловаться. Однако вы можете инициализировать массив указателей на свой объект, но вы действительно получите большую гибкость с вектором, поэтому в моих следующих примерах будет использоваться std :: vector.

Вам нужно будет инициализировать каждый объект отдельно, если вы хотите, чтобы каждый объект имел определенное значение, вы можете сделать это одним из двух способов; в стеке или в куче. Сначала посмотрим на стек.

Любой конструктор, который принимает один аргумент и не помечен как explicit, может использоваться как неявный конструктор. Это означает, что в любом месте, где ожидается объект такого типа, вы можете вместо этого использовать экземпляр одного типа параметров. В этом примере мы создаем вектор вашего класса Object и добавляем к нему 100 объектов (push_back добавляет элементы в вектор), мы передаем целое число в push_back, который неявно создает объект, передаваемый в целое число.

#include <vector> 
int main() { 
    std::vector<Object> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(i); 
    } 
} 

Или быть явно об этом:

#include <vector> 
int main() { 
    std::vector<Object> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(Object(i)); 
    } 
} 

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

Один из способов обойти эту проблему производительности, чтобы выделить объекты на кучу и хранить указатели на объекты в вашем векторе:

#include <vector> 
int main() { 
    std::vector<Object*> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(new Object(i)); 
    } 

    for(int i = 0; i < 100; i++) { 
     delete v[i]; 
    } 
} 

Поскольку наши объекты были созданы в куче мы должны убедиться, что мы удаляем их для вызова их деконструктора и, освобождая их память, этот код делает это во втором цикле.

Ручной вызов delete имеет свои оговорки, если вы передадите эти указатели на другой код, вы можете быстро потерять информацию о том, кто владеет указателями, и кто должен их удалить. Более простой способ решения этой проблемы является использование смарт-указатель для отслеживания срока службы указателя см либо boost::shared_ptr или tr1::shared_ptr, которые являются ориентирами подсчетом указатели:

#include <vector> 
int main() { 
    std::vector<shared_ptr<Object> > v; 

    for(int i = 0; i < 100; i++) { 
     Object* o = new Object(i); 
     v.push_back(shared_ptr<Object>(o)); 
    } 
} 

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

+0

Спасибо за следовать до. Это тоже очень помогло! – banDedo

0

Если вы хотите придерживаться массивов, вы должны либо инициализировать вручную, либо использовать конструктор по умолчанию. Однако вы можете получить некоторый контроль, создав конструктор с аргументом по умолчанию. Этот компилятор будет рассматриваться как конструктор по умолчанию. Например, следующий код печатает цифры 0, ..., 9 по порядку. (Тем не менее, я не уверен, что стандарт требует, чтобы объекты в массиве должны быть построены в порядке. Это может быть зависят от конкретной реализации, и в этом случае цифры могут появляться в произвольном порядке.)

#include <iostream> 

using namespace std; 

struct A { 
    int _val; 

    A(int val = initializer()) : _val(val) {} 

    static int initializer() { static int v = 0; return v++; } 
}; 

int main() 
{ 
    A a[10]; 
    for(int i = 0; i < 10; i++) 
     cout << a[i]._val << endl; 
} 
Смежные вопросы