ссылка на указанный объект - PullRequest
3 голосов
/ 20 января 2010

Разыменование указателей может затруднить чтение кода.Я обычно делаю ссылку на указанный объект и работаю со ссылкой.Пример:

shared_ptr<std::vector<int> > sp = get_sp_to_vector();
std::vector<int>& vec = *sp;
...
vec.push_back(5);

Интересно, хорошая ли это практика?Есть ли у него недостатки?

Обновление: Чтобы завершить пример, я бы определил get_sp_to_vector() следующим образом:

shared_ptr<std::vector<int> >  get_sp_to_vector()
{
    // create a vector and send back a shared pointer pointing at it
    shared_ptr<std::vector<int> >  sp(new std::vector<int>);
    sp->push_back(1);  sp->push_back(3);
    return sp;
}

Ответы [ 5 ]

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

Распространено использование локальных ссылок, особенно внутри тел цикла, но есть одно требование: делайте это только тогда, когда ссылка явно будет жить столько же, сколько и целевой объект.

Обычно это не сложно гарантировать, но вот несколько плохих примеров:

shared_ptr<X> p = get_p();
X& r = *p;
p.reset(); // might result in destroying r
use(r); // oops

// or:
shared_ptr<X> p = get_p();
X& r = *p;
p = get_some_other_p(); // might result in destroying r
use(r); // oops
2 голосов
/ 20 января 2010

ИМХО, я думаю, что это приемлемая практика (с некоторыми оговорками - см. пост Роджера Пейта ).Если вы добавляете строку кода только для вызова push_back (), то я не думаю, что это приемлемо.

Однако, если вы обнаружите, что разыменовываете указатель много раз, то не только разыменование его раз в ссылочном объекте приемлемо, но и выигрыш в производительности (в зависимости от вашего компиляторарассматриваемый код, фазы Луны и т. д.).

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

Я бы не стал считать это хорошей практикой. Указатели являются основным приоритетом разработки на C / C ++, и, б / у, кодеры C / C ++ удобны в использовании синтаксиса де-ссылки, необходимого указателям. Я стараюсь избегать использования указателей, когда это возможно (хотя и не по синтаксическим причинам), но иногда это просто лучший инструмент для работы. Если у вас есть код, который является грубым b / c, вы используете указатель, я бы, как правило, удалил его из ссылки в функцию, которая передает объект по ссылке, которая, по сути, делает то, что вы делаете, но, по моему мнению, это делает более элегантный способ. Так что вместо:

shared_ptr<std::vector<int> > sp = get_sp_to_vector();
std::vector<int>& vec = *sp;
...ugly stuff...
vec.push_back(5);

Я бы сделал:

void func(std::vector<int> &vec)
{
     ... previously ugly stuff...
     vec.push_back(5);
}

shared_ptr<std::vector<int> > sp = get_sp_to_vector();
func(*sp);

EDIT:
Это не означает, что вы должны создать функцию просто для создания более приятного синтаксиса для указателей, поскольку это означает, что если вам не нравится синтаксис указателя и ваш код использует чистые и лаконичные функции, вы можете просто заставить функции принимать ссылки и разыменование вашего указателя при вызове функции. Для ситуаций, когда у вас есть только несколько вызовов * p или p-> x, кажется глупым создавать функцию со ссылкой или создавать ссылку для вызова p.x. Просто используйте синтаксис указателя в этих случаях, так как это синтаксис C / C ++.

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

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

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

shared_ptr<std::vector<int> > sp = get_sp_to_vector();
...
sp->push_back(5);

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

Возможно, если ваш код указателя очень трудно читатьЭто потому, что вы упускаете какой-то трюк, который сделает его проще.Возможно, если вы зададите другой вопрос с примером неверного кода указателя, который в настоящее время исправляете с помощью ссылки, SOers найдет альтернативные исправления.

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

Если я на самом деле занимаюсь манипулированием указателем, тогда я оставляю указатель. Если мой указатель является просто нулевой ссылкой, то я оставляю указатель. Если я уверен или хочу убедиться, что указатель всегда будет ненулевым (Т. Е. Если я возвращаю ненулевой объект из метода), то Я делаю это явно, используя ссылку.

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