2014-01-04 3 views
2

У меня возникли проблемы с пониманием того, как использовать динамическое распределение с помощью конструкторов.C++: оператор new и конструктор по умолчанию

Я использую в своем коде класс с именем graph (который представляет собой всего лишь двухмерную матрицу bool, представляющую ребра между узлами) со следующим конструктором/деструктором (есть другие методы, но я не думаю, что это имеет значение здесь):

class graph{ 

private: 
bool** edges; 
int size; 

public: 
graph(int size = 0):size(size){ 
    edges = new bool*[size]; 
    for (int i = 0; i < size; i++){ 
     edges[i] = new bool[size]; 
    } 
} 

~graph(){ 
    for(int i = 0; i < size; ++i) { 
     delete [] edges[i]; 
    } 
    delete [] edges; 
} 

//others methods 

}; 

в моем главном, я хочу использовать динамическое распределение:

int main() 
{ 

    int size; 
    cout << "Enter graph size :" << endl; 
    cin >> size; 

    graph g1 = new graph(size); 

    //some processing code 

    return 0; 
} 

Howewer, я получаю сообщение об ошибке на конкретизации (т.е. нового графика (размер)):

недействителен преобразование из «графа *» до «» межд [-fpermissive]

Я не получить то, что происходит не так, и я уверен, что это синтаксис я уже видел в других местах.

На самом деле, я действительно не понимаю, как распределение памяти работает с созданием объекта.

Здесь я использую новый в моем конструкторе для создания bool 2d-матрицы, так что это будет куча, нет? Но если я инициализирую объект, используя следующую статическую инструкцию: graph g1 (const_size);

Тогда это не значит, что нужно идти в стек?

Заранее благодарю вас за ответы.

EDIT

Только один последний вопрос:

график * g1 = новый график (размер);

хранит g1 (указатель) в стеке, но объект создается в куче.

g1 (размер);

создает объект в стеке, а g1 является ссылкой на него.

Но в любом случае края матрицы будут находиться на куче? Или во втором случае это как-то закончится в стеке?

+0

'graph * g1 = ...' но серьезно, * почему * вам нужно динамическое размещение там? – juanchopanza

+0

По правде говоря, было больше понять, как я мог бы это сделать, если бы это было необходимо. Мне это действительно не нужно прямо сейчас. Но, например, если мне нужна программа, которая может иметь дело с разным размером графика, не перекомпилируя ее каждый раз, когда я хочу работать с другим размером, мне нужно что-то подобное, нет? – Demod

+0

Не в основном. Там вы можете просто сказать 'graph g1 (42);' – juanchopanza

ответ

3

Ошибка здесь:

graph g1 = new graph(size); 

Это должно быть:

graph *g1 = new graph(size); 

Причина заключается в следующем:

new graph(size) 

создает новый объект и возвращает указатель к нему (с номером graph*) и:

graph g1 = ... 

пытается преобразовать, что возразить int (для того, чтобы вызвать graph(int) конструктор) - поэтому ошибка invalid conversion from 'graph*' to 'int'.

Теперь, я полагаю, это какое-то упражнение, так как вы не должны использовать распределение в куче в этом примере. Но если вы используете его в любом случае, никогда не забывайте:

delete g1; 

На самом деле, я действительно не понимаю, как распределение памяти работает с созданием объекта.

graph *g1 = new graph(size); 

хранит g1 (указатель) на стек, но объект создается в куче.

graph g1(size); 

создает объект в стеке, и g1 является ссылкой на него.

P.S. Избежать этого:

graph g1 = graph(const_size); 

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

Но, например, если мне нужна программа, которая может иметь дело с разным размером графика, не перекомпилируя ее каждый раз, когда я хочу работать с другим размером, мне нужно что-то подобное, нет?

Нет, вы можете использовать для этого распределение стека (я только заметил, что в вашем примере вы используете параметр const_size для конструктора объекта, выделенного в стеке, не обязательно быть постоянным):

int size; 
std::cout << "Enter size: "; 
std::cin >> size; 
graph g1(size); 

Да, динамическое распределение не нужен здесь, я просто сделал этот код на практике себя. Но это было бы необходимо, если бы я хотел работать с разным размером графика без перекомпиляции, нет?

Нет, посмотрите на пример прямо над этим - стек назначил объект с переменным размером - без перекомпиляции.

Я думал, что мы не должны сами называть деструктора и что это все равно будет вызвано, когда мы выйдем из сферы действия? (Я даже читал, что это было на самом деле плохо назвать это в некоторых случаях, как это могло бы называть его во второй раз)

Это верно в случае стека выделенных объектов - деструктор будет вызван в конце объем. Однако, если вы выделяете объект в кучу, деструктор не вызывается до тех пор, пока вы не назовете delete.

Но в любом случае края матрицы будут находиться на куче?

edges = new bool*[size]; 
    for (int i = 0; i < size; i++){ 
     edges[i] = new bool[size]; 
    } 

Да, вся матрица выделяется на куче.

+0

Хорошо, спасибо вам большое. Очень ясный ответ. Да, динамическое распределение здесь не требуется, я просто сделал этот код, чтобы попрактиковаться. Но это было бы необходимо, если бы я хотел работать с графиком разного размера без перекомпиляции, нет? Я думал, что мы не должны были сами назвать деструктора и что это все равно будет вызвано, когда мы выйдем из сферы действия? (Я даже читал, что в некоторых случаях было бы неправильно называть его, поскольку это может вызвать его второй раз). PS: Да, я понял ошибку сразу после написания, я имел в виду график g1 (размер) – Demod

+0

@Demod см. Редактирование! –

+0

Спасибо, я также отредактировал исходное сообщение, потому что у меня был последний вопрос о том, где переменная bool ** edge. – Demod

Смежные вопросы