C ++ векторы классов с конструкторами - PullRequest
5 голосов
/ 09 августа 2010
//Using g++ and ubuntu.
#include <vector>
using namespace std;

Определить класс:

class foo(){
(...)
foo(int arg1, double arg2);
}

Конструктор:

foo::foo(int arg1, double arg2){ 
(...) //arrays whose length depend upon arg1 and arg2
} 

Я хотел бы сделать что-то вроде этого:

vector<foo> bar(10); //error: no matching function for call to 'foo::foo()'
bar[0] = new foo(123, 4.56);
(...)

Альтернативаметод (который мне нравится меньше) заключается в использовании push_back:

vector<foo> bar; //works
bar.push_back(new foo(123, 4.56)); //throws similar error.
//Omitting the "new" compiles but throws a "double free or corruption (fasttop)" on runtime.

Я хочу, чтобы разные элементы вектора создавались по-разному, поэтому я не хочу использовать «Конструктор повторяющихся последовательностей».Что должно быть сделано?

Ответы [ 3 ]

4 голосов
/ 09 августа 2010
vector<foo> bar(10); //error: no matching function for call to 'foo::foo()'

Это сбой, потому что вы вызываете std::vector конструктор

explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );

Как видите, он пытается заполнить вектор 10 вызовами конструктора по умолчанию foo, который не существует.

Кроме того, все ваши примеры с new потерпят неудачу, потому что вектор ожидает объект типа foo, а не foo *. Кроме того, изменение на vector<foo *> также не удастся, если вы вручную не уберете delete каждый элемент перед очисткой вектора. Если вы действительно хотите пойти по пути динамического выделения памяти, создайте vector< shared_ptr< foo > >. shared_ptr доступно в библиотеках Boost , или если ваш компилятор включает библиотеки TR1, он будет присутствовать в заголовке <memory> в пространстве имен std::tr1 или если ваш компилятор имеет библиотеки C ++ 0x, будет доступен в самом пространстве имен std.

Вероятно, вам следует сделать следующее:

vector<foo> bar;
bar.reserve(10);
bar.push_back( foo( 1, 2 ) );
...
...
bar.push_back( foo( 10, 20 ) ); //10 times
4 голосов
/ 09 августа 2010

Почему вы используете new, когда не нужно создавать динамическую память? Конечно, использование new не удастся, это приведет к foo*, когда push_back примет foo. (Это то, что у вас есть вектор, в конце концов.)

Что не так с push_back? Если вы хотите зарезервировать память заранее, используйте reserve(); предоставление числа в конструкторе vector делает столько копий второго параметра (который неявно равен foo(), который не будет работать, следовательно, ваши ошибки), что не то же самое, что просто резервирование памяти.

Если все происходит правильно (нет new), происходит сбой, ошибка в вашем коде, а не в векторе. Возможно, вы не написали правильный класс, который управляет ресурсами. * (Помните Большая тройка , используйте идиома копирования и замены .)

* Я говорю это, потому что вы говорите "//arrays whose length depend upon arg1 and arg2 ", что, я подозреваю, означает, что у вас есть new[] в вашем классе где-то. Без Большой Тройки ваше управление ресурсами потерпит неудачу.

Вы все равно не должны управлять ресурсами, классы несут одну ответственность. Это означает, что он должен быть либо динамическим массивом, либо использовать динамический массив, но не одновременно управлять и использовать динамический массив. Поэтому выделите ресурсы в их собственный класс, а затем создайте другой (ваш) класс, который их использует. Динамический массив - std::vector, так что вы уже закончили с этим. В любой раз, когда вам нужен динамический массив, используйте vector; нет причины не делать этого.

0 голосов
/ 09 августа 2010

std :: vector всегда создает элементы на основе конструктора по умолчанию, который вы не определили во фрагменте выше.

метод push_back сталкивается с проблемой двойного освобождения, поскольку вы не обрабатывали конструктор копирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...