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

С++ - когда следует использовать элемент указателя в классе

Одна из вещей, которая сбивала меня с толку при изучении С++ (и Direct3D, но что-то давно), - это когда вы должны использовать элемент-указатель в классе. Например, я могу использовать объявление без указателя:

private:
    SomeClass instance_;

Или я мог бы использовать объявление указателя

private:
   Someclass * instance_

И затем используйте new() на нем в конструкторе.

Я понимаю, что если SomeClass может быть получен из другого класса, COM-объекта или ABC, то он должен быть указателем. Есть ли другие рекомендации, о которых я должен знать?

4b9b3361

Ответ 1

Указатель имеет следующие преимущества:

a) Вы можете выполнить ленивую инициализацию, то есть инициализировать/создать объект, только короткий до первого реального использования.

b) Конструкция: если вы используете указатели для членов внешнего типа класса, вы можете разместить перед собой объявление вперед над вашим классом и, следовательно, не нужно включать заголовки этих типов в свой заголовок, вместо этого вы включая заголовки сторонних производителей в вашем .cpp - это имеет преимущество, чтобы сократить время компиляции и предотвратить побочные эффекты, включив слишком много других заголовков.

class ExtCamera;  // forward declaration to external class type in "ExtCamera.h"

class MyCamera {
public: 
  MyCamera() : m_pCamera(0) { }

  void init(const ExtCamera &cam);

private:
   ExtCamera  *m_pCamera;   // do not use it in inline code inside header!
};

c) Указатель может быть удален в любое время, поэтому вы можете больше контролировать жизненное пространство и можете воссоздать объект - например, в случае сбоя.

Ответ 2

Преимущества использования указателя описаны 3DH: ленивая инициализация, сокращение зависимостей заголовков и контроль над временем жизни объекта.

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

Другим недостатком является действительно оборотная сторона контроля над временем жизни объекта, на который указывает указатель. Элементы данных без указателя автоматически уничтожаются при уничтожении объекта, что означает, что вы всегда можете быть уверены, что они существуют до тех пор, пока объект существует. С указателем вы должны проверить, что это nullptr, что означает также, что вы должны установить его в nullptr всякий раз, когда он не указывает на что-либо. Чтобы иметь дело со всем этим, это может легко привести к ошибкам.

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

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

Ответ 3

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

Причина, по которой вы видите много использования указателей, когда дело касается игр и т.д., заключается в том, что DirectX является COM-интерфейсом, и, честно говоря, большинство программистов игр со спины в тот же день не являются программистами на С++, они C-with -классы программистов, а использование C-указателей очень распространено.

Ответ 4

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