разные способы реализации - PullRequest
0 голосов
/ 20 ноября 2011

Мне любопытно, в чем разница:

Trie* trie = new Trie();

и

Trie trie;

Полагаю, что в первом случае trie - это просто указатель на объект, во втором случае trie - это сам объект. Но какая разница на практике? Когда использовать каким способом?

Или некоторые из них являются "предпочтительным" стилем?

Ответы [ 3 ]

3 голосов
/ 20 ноября 2011

Это показывает, что вам нужно серьезно начать изучать C ++ из книги. Ответ на этот вопрос будет очень долгим, поскольку эти два понятия очень разные.

Короче говоря, вот несколько подсказок для вас:

Trie* trie = new Trie();

Распределяет память в куче, вы получаете указатель на выделенную память, и вам нужно delete, когда вы закончите с ней.

Trie trie;

Выделяет trie в стеке, и объект уничтожается, как только заканчивается его область действия.

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

Первый имеет стоимость времени выполнения, а второй - нет (или очень очень мало).

С первым вы можете выделить всю необходимую вам память (столько памяти, сколько у вас есть), в то время как со вторым вы связаны размером стека.

Редактировать: Ответ на ваш первый комментарий

Стек выделяется операционной системой при загрузке программы. Компилятор не принимает какого-либо определенного размера для стека и, действительно, при каждом вызове функции или вообще при вводе новой области видимости просто идет и записывает дальше в стек. Если у вас есть рекурсивные функции, которые идут слишком глубоко, вы действительно получите ошибку ошибки сегментации (нарушение доступа).

С другой стороны, куча - это весь пул памяти, который имел компьютер, и управляла операционной системой. Вызов new запрашивает памяти из операционной системы. Если памяти недостаточно, операционная система может отклонить запрос, и вы получите NULL (Примечание: после каждого new вы должны проверять, равен ли результат NULL или нет. Если это NULL , вы должны обработать этот неудачный случай. В противном случае ваша программа потерпит крах). Точно так же, когда вам больше не нужна память, вы должны delete. Также обратите внимание, что delete вызывает деструктор вашего объекта и, таким образом, на самом деле имеет решающее значение для нормальной программы.

1 голос
/ 20 ноября 2011

Все дело в жизни.

Если время жизни связано с временем жизни его объявления, то второе имеет смысл. Если время жизни больше, тогда вы обычно используете первое (хотя обычно лучше использовать shared_ptr какого-то рода, чтобы не было утечек памяти).

например. если мне нужен Trie на время выполнения функции или метода:

void MyFun()
{
  Trie trie;
  // use my trie...
  ...
  // now trie (instance of Trie) dies - no leaks, can't be accessed by anyone else, better not have given out pointers or references to it that exist beyond this point!!!
}

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

class C
{
public:
    C() : trie(args..) { }
private:
    Trie trie;   // <- this instance will live exactly as long as it's instance of C does
};

Однако, если вам нужно, чтобы экземпляры Trie существовали в течение произвольной продолжительности или имели переменное число потребителей, вы используете указатели (или если Trie копирует дорого, или содержит внешние ресурсы или хрупкое состояние). Но это гораздо более сложное обсуждение, и его следует рассмотреть в более длинном трактате по базовому C ++.

0 голосов
/ 20 ноября 2011

Это указатель на класс Trie: Tire *trie; Этот указатель указывает на неопределенное место в памяти, потому что вы не присвоили ему адрес памяти, используя new. Если вы попытаетесь использовать неопределенный указатель, это вызовет исключение и завершит вашу программу (поскольку неопределенный указатель ни на что не указывает). Когда вы используете оператор: Trie *trie = new Trie();, вы просите компьютер выделить достаточно байтов для хранения одного объекта Trie в куче и вернуть этот адрес памяти указателю trie. Когда вы используете оператор Trie trie;, вы просите компьютер выделить достаточно байтов для хранения одного Trie объекта в стеке.

...