Когда передавать по ссылке и когда передавать по указателю в C ++?

Типичные ситуации:

  1. Передача std :: string в функцию foo (std :: string *) или foo (std :: string &);
  2. Передача tr1 :: shared_ptr в функцию foo (tr1 :: shared_ptr * ptr) или foo (tr1 :: shared_ptr & ptr);

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

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

Считаете ли вы следующий фрагмент хорошим?

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <tr1/memory>
#include <algorithm>
using namespace std;
using namespace std::tr1;

int main(){
        map<string, shared_ptr<vector<string> > > adjacencyMap;
        vector<string>* myFriends = new vector<string>();
        myFriends->push_back(string("a"));
        myFriends->push_back(string("v"));
        myFriends->push_back(string("g"));
        adjacencyMap["s"] = shared_ptr<vector<string> >(myFriends);
        return 0;
}

Спасибо Ajay

46
задан sbi 31 August 2010 в 21:00
поделиться

3 ответа

Ссылки легче сделать правильными.

Ваша проблема с литералами в том, что вы не используете константные ссылки? Вы не можете привязать временную (созданную литералом) ссылку к неконстантной ссылке, потому что нет смысла ее менять. Вы можете привязать один к константной ссылке.

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

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

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

26
ответ дан 26 November 2019 в 20:33
поделиться

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

  • передавать по значению (для дешевого копирования объектов, всех примитивов, малых типов значений, std::string, очень маленькие строки или строки с повторным подсчетом)
  • передавать по const ссылка (для доступа к большим объектам только для чтения)
  • передать по указателю, если вам нужен доступ для чтения и записи

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

6
ответ дан 26 November 2019 в 20:33
поделиться

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

Какова цель NULL? Для указания недопустимого указателя/объекта. Если вы собираетесь передавать недопустимые объекты в функцию, все, что вам нужно сделать, это иметь метод для проверки правильности объекта. Как в:

void myfunc(const obj& myobj)
{
  if(myobj.valid())
    // DO SOMETHING
}

Примитивные типы, которые вы обычно хотели бы передавать по значению, так как это так мало накладных расходов. И именно тогда вы все равно будете использовать литералы большую часть времени. Для строк вы должны попытаться использовать std::string и держаться подальше от const char* строк в стиле C, насколько это возможно. Конечно, если вам нужно использовать C-строки, у вас нет другого выбора, кроме как использовать указатели, но в целом ссылки должны быть правильным способом.

О, и, чтобы быть действительно безопасным для исключений, постарайтесь избежать этого:

vector<string>* myFriends = new vector<string>();
...
adjacencyMap["s"] = shared_ptr<vector<string> >(myFriends);

Вместо этого сделайте:

shared_ptr<vector<string> > myFriends(new vector<string>());

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

2
ответ дан 26 November 2019 в 20:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: