Когда использовать указатели в C ++ - PullRequest
6 голосов
/ 30 января 2010

Я только начал изучать указатели в C ++, и я не очень уверен, когда использовать указатели, а когда использовать реальные объекты.

Например, в одном из моих назначений мы должны создать класс gPolyline, где каждая точка определяется gVector. Прямо сейчас мои переменные для класса gPolyline выглядят так:

private:
vector<gVector3*> points;

Если бы вместо этого у меня было vector points , какая разница? Кроме того, есть ли общее правило, когда следует использовать указатели? Заранее спасибо!

Ответы [ 5 ]

2 голосов
/ 30 января 2010

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

Если вы используете vector<gVector3>, вставка элементов сделает копии этих элементов, и элементы больше не будут связаны с вставленным элементом. Когда вы храните указатели, вектор просто ссылается на вставленный вами объект.

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

1 голос
/ 30 января 2010

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

Сначала необходимо узнать, удовлетворяет ли gVector3 требованиям стандартных контейнеров, а именно, можно ли копировать и назначать тип gVector3. Это полезно, если gVector3 также является конструктивным по умолчанию (см. Примечание ОБНОВЛЕНИЕ ниже). Предполагая, что это так, у вас есть два варианта, хранить объекты gVector3 непосредственно в std::vector

std::vector<gVector3> points;
points.push_back(gVector(1, 2, 3)); // std::vector will make a copy of passed object

или управляйте созданием (а также уничтожением) gVector3 объектов вручную.

std :: vector points; points.push_back (новый gVector3 (1, 2, 3)); //...

Когда массив points больше не нужен, не забудьте обсудить все элементы и вызвать на нем оператор delete.

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

gVector3 v1(1, 2, 3);
gVector3 v2;
v2 = v1; // assignment
gVector3 v3(v2); // copy construction

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

Кстати, вам может быть интересно Когда я должен использовать ссылки, а когда я должен использовать указатели?

ОБНОВЛЕНИЕ: Вот пояснение к примечанию по конструктивности по умолчанию . Спасибо Нейлу за то, что он указал, что это было первоначально неясно. Как правильно заметил Нил, это не требуется стандартом C ++, однако я указал на эту функцию, потому что она важна и полезна. Если тип T не является конструируемым по умолчанию, что не требуется стандартом C ++, тогда пользователь должен знать о потенциальных проблемах, которые я попытаюсь проиллюстрировать ниже:

#include <vector>
struct T
{
    int i;
    T(int i) : i(i) {}
};
int main()
{
    // Request vector of 10 elements
    std::vector<T> v(10); // Compilation error about missing T::T() function/ctor
}
1 голос
/ 30 января 2010

Указатели, как правило, следует избегать в современном C ++. В настоящее время основная цель указателей заключается в том, что указатели могут быть полиморфными, а явные объекты - нет.

Когда вам нужен полиморфизм в наше время, хотя лучше использовать класс интеллектуальных указателей, например std::shared_ptr (если ваш компилятор поддерживает расширения C ++ 0x), std::tr1::shared_ptr (если ваш компилятор не поддерживает C ++ 0x, но поддерживает TR1) или boost::shared_ptr.

0 голосов
/ 30 января 2010

Обычно вы используете объекты.
Яблоко легче съесть, чем яблоко на палочке (ОК, двухметровая палочка, потому что я люблю леденцы).

В этом случае просто сделайте его вектором

Если у вас был вектор , это означает, что вы динамически размещаете новые объекты g3Vector (используя оператор new). Если это так, то вам нужно в какой-то момент вызывать delete для этих указателей, и std :: Vector не предназначен для этого.

Но каждое правило является исключением.

Если g3Vector - огромный объект, копирование которого стоит очень дорого (трудно сказать, прочитайте вашу документацию), тогда может быть более эффективно хранить его в качестве указателя. Но в этом случае я бы использовал boost :: ptr_vector , так как это автоматически управляет продолжительностью жизни объекта.

0 голосов
/ 30 января 2010

Вы можете использовать указатели или объекты - это действительно то же самое в конце дня.

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

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

Поместить сами объекты в структуру STL проще и проще. Требуется меньше операторов * и ->, которые могут оказаться трудными для понимания. В некоторых объектах STL должны присутствовать сами объекты вместо указателей в их формате по умолчанию (т.е. хеш-таблицы, которые должны хешировать запись - и вы хотите хешировать объект, а не указатель на него), но вы всегда можете обойти это переопределяющие функции и т. д.

Итог: используйте указатели, когда это имеет смысл. В противном случае используйте объекты.

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