Подтвердить что ты не робот

Когда использовать указатели, а когда нет?

Я привык к программированию на Java, где вам никогда не нужно думать о указателях при программировании. Однако на данный момент я пишу программу на С++. При создании классов, которые имеют члены других классов, когда я должен использовать указатели, а когда нет? Например, когда я хочу это сделать:

class Foo {
    Bar b;
}

В противоположность этому:

class Foo {
    Bar* b;
}
4b9b3361

Ответ 1

Начать, избегая указателей.

Используйте их, когда:

  • Вы хотите использовать Pimpl idiom или abstract factory.
  • Экземпляр Bar фактически управляется какой-либо другой частью вашей программы, тогда как класс Foo должен иметь доступ к нему.
  • Вы хотите отложить построение объекта Bar (т.е. вы хотите создать его после построения Foo).
  • В вашей бизнес-логике объект Bar может вообще отсутствовать; вы бы использовали null также в Java. Однако проверьте boost:: optional.
  • Bar на самом деле является базовым классом, и вам нужно, чтобы экземпляр был полиморфным.
  • Вы используете инструментарий, который предпочитает отображать графические элементы GUI в качестве указателей. Примеры могут включать (но, без ограничений) wxWidgets и GLUI.

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

(*) в любом случае - кроме, вероятно, пули относительно виджетов GUI; в этом случае ваш инструментарий, скорее всего, также будет управлять ресурсами для вас.

Ответ 2

class Foo {
    Bar b;
}

b содержится в Foo. Если объект Foo заканчивается на всю жизнь, b автоматически завершает время жизни. Это то, что моделирует композицию. b выше обозначает сам объект, а не только указатель на него, как на Java. Поэтому, если b выходит за пределы области действия, объект заканчивается на всю жизнь.

class Foo {
    Bar * b;
}

Здесь объект b указывает, что используется или ссылается на объект Foo. Если объект Foo заканчивается на всю жизнь, объект b указывает, что он может продолжать жить, в зависимости от обстоятельств. Это можно использовать для моделирования агрегации и общих отношений. Например, объект может совместно использоваться другими объектами Foo.

Указатели примерно соответствуют ссылкам на Java. Они также могут указывать на ничего. Если указатель указывает на ничего, это нулевой указатель.

Подобно указателям - ссылки. Ссылки на С++ должны быть инициализированы и могут указывать только на один (действительный) объект, для которого была инициализирована ссылка. Ссылка на них не может содержать значение, которое может означать "ничего", как null в Java.

Ответ 3

В первом примере память для объекта Bar будет автоматически назначаться при создании объекта Foo. Во втором случае вам нужно выделить память самостоятельно. Поэтому вы должны позвонить:

Foo *foo = new Foo();
foo->b = new Bar();

Это может быть желательно, если объект Bar большой, и вы не хотите связывать его с объектом Foo. Также желательно, когда конструкция объекта Bar не зависит от создания объекта Foo. В этом случае объект b "впрыскивается" в foo:

Foo *foo = new Foo();
foo->b = b_ptr;

где b_ptr строится где-то еще, и указатель передается в foo.

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

Ответ 4

Оба в порядке в разных условиях. Например, если вы знаете, как построить b, когда объект класса Foo сконструирован, первое - ОК. Но если вы этого не сделаете, единственный выбор - использовать второй.

Ответ 5

Вам нужно выполнить некоторые сборки и хорошо понять схему памяти. C - это просто кроссплатформенная сборка, в отличие от Java или других языков. Чтобы использовать его правильно, нужно понимать детали низкого уровня.

Все сделанные комментарии действительны, но для таких людей, как вы, которые перескакивают с языков высокого уровня на C, такой опыт будет более чем полезным. При правильном понимании вы больше не будете задавать такие вопросы.