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

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

Общие ситуации:

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

В общем, что такое хорошая практика. Я всегда смущаюсь. Во-первых, передача всего, поскольку ссылки кажутся согласованными, однако в Литералах невозможно передать ссылки или 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;
}

Спасибо Аджай

4b9b3361

Ответ 1

Ссылки на них легче получить.

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

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

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

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

Ответ 2

Хорошее эмпирическое правило: "Используйте ссылки, когда можете, и указатели, когда вам нужно".

Ответ 3

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

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

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

Ответ 4

Я действительно не понимаю, почему вы столкнулись со всей этой неприятностью:

std::map < std::string, std::vector<std::string> > adjacencyMap;
std::vector<std::string>& sFriends = adjacencyMap["s"];
sFriends.push_back("a");
sFriends.push_back("v");
sFriends.push_back("g");

Почему вы вмешиваетесь в shared_ptr здесь? Ситуация, конечно же, не требует этого!

Ответ 5

Вероятно, не ответ на вопрос. Просто KISS.

int main()
{
        multimap<string, string> adjacencyMap;
        adjacencyMap.insert(std::make_pair("s", "a"));
        adjacencyMap.insert(std::make_pair("s", "v"));
        adjacencyMap.insert(std::make_pair("s", "g"));
        return 0;
}

Ответ 6

Вы можете просмотреть http://www.cplusplus.com/forum/beginner/3958/ для некоторых идей. Также полезно: http://www.velocityreviews.com/forums/t284603-pointers-vs-references-a-question-on-style.html

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

Я лично предпочитаю ссылки, но я рекомендую в любом случае прочитать эти сообщения и обсудить их.

Ответ 7

Как правило, всегда старайтесь передавать параметры по ссылке на 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 и безопасность исключений, почему это предпочтительный метод.

Ответ 8

Я бы предпочел

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

так как это гарантирует, что локальная обработка var небезопасна.

Я действительно не вижу, как это относится к вашему q, который был о достоинствах ref vs ptr. В обоих примерах, которые вы цитируете, я ожидаю использовать вторую форму (ref).