2017-01-04 3 views
0

После нескольких лет, не касаясь C++, я возвращаюсь к нему и решил снова учиться с помощью учебника («Sutherland, Bruce, Learn C++ for Game Development» (стр. 59) Apress. Kindle Edition. "). У меня 2 простых вопросов:Передача значений в качестве опорных значений и значений «const»

1) В одном примере, в книге используются следующие строки кода для вызова функции:

string playerInput; 
GetPlayerInput(playerInput); 

И сама функция определяется как:

void GetPlayerInput(string& playerInput) 
{ 
    cin >> playerInput; 
} 

Вопрос: Провод «playerInput» передается как «строка &». Это действительно необходимо? Почему это передается в качестве ссылки, когда мы могли бы сделать функцию возвращать строку и сделать это следующим образом:

string playerInput; 
playerInput = GetPlayerInput(); 

И:

string GetPlayerInput() 
{ 
    cin >> playerInput; 
    return playerInput; 
} 

Является ли это просто стилистический выбор, или я что-то не хватает Вот?

2) акцесор класса, чтобы получить имя пользователя был определен как:

'void SetName(const std::string& name);' 

Нет другого объяснения. Что случилось с этой «созвездием»? Я сделал некоторые исследования, но только больше смутился. Зачем вам это нужно при передаче строки в качестве параметра (и снова как ссылка?)

Большое вам спасибо за помощь!

+0

Вот хороший список из [C++ books] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Очень хорошо объяснено в книгах Скотта Мейерса. –

+0

взгляните на концепцию пропуска по значению и перейдите по ссылке. Если вы передаете по значению, то вы бесполезно вызываете конструктор копирования (в зависимости от требования) и const, потому что вы можете не захотеть случайно записать его, когда вам этого не нужно. И согласно одному предложению, пожалуйста, прочитайте книгу Скотта Мейерса –

+0

. Книга теперь находится в моем списке «читать» следующее :-) –

ответ

1

1) В принципе, возврат по значению включает в себя копию. Тем не менее, практически все компиляторы выполняют RVO/NRVO даже в режиме отладки.

Таким образом, в целом это выбор API, однако он может быть значительным при использовании в цикле. Сравните эти два, например:

for (;;) { 
    string playerInput = GetPlayerInput(); 
    if (playerInput.empty()) break; 
    // do something with the playerInput 
} 

string playerInput; 
for (;;) { 
    GetPlayerInput(playerInput); 
    if (playerInput.empty()) break; 
    // do something with the playerInput 
} 

Существует тонкая разница, которая делает более поздний случай более совершенным. В первом случае, даже с NRVO, строка вновь назначается каждый раз. Во втором случае, наоборот, строка только выделяется/перераспределяется несколько раз, а в конце она имеет размер самого длинного входа.

Кроме того, GetPlayerInput может затем вернуться bool, что позволит сделать цикл выглядит намного лучше:

string playerInput; 
while (GetPlayerInput(playerInput)) { 
    // do something with the playerInput 
} 

2) Передача по константной исх (в отличие от неконстантного исх) не только делает невозможным изменять параметр по ошибке, но также позволяет использовать временные, что, возможно, даже более важно.В качестве примера:

setName("Some name"); 

не работает с бесконтактными ссылками.

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

Единственный случай, когда это целесообразно использовать проход по значению, когда вы скопировать параметр внутренне все равно, как, например:

SomeClass operator +(SomeClass a, const SomeClass& b) { 
    return a += b; 
} 

вопреки

SomeClass operator +(const SomeClass& a, const SomeClass& b) { 
    SomeClass result = a; 
    return result += b; 
} 
+0

Более важная часть № 2, которую вы забыли, состоит в том, что передача 'std :: string' вместо' const std :: string & 'может копировать, еще раз, это просто для оптимизации. –

+0

Правильно, однако я сравнивал передачу «' std :: string & '" vs "' const std :: string & '". Но верно, что ОП также задает вопросы. – axalis

+0

Спасибо всем за ответы/комментарии. Я, возможно, слишком много прыгаю, задавая такие вопросы (может быть, они будут отвечены естественным образом, поскольку я продолжал учиться и практиковаться), но теперь это имеет гораздо больше смысла! Опять же, жаль новых вопросов, но очень ценю помощь. –

0

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

Смежные вопросы