Передача строкового литерала в функцию, ожидающую строку - PullRequest
0 голосов
/ 23 октября 2019

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

   void str(string &s); // my function which is expecting a non const string
   // main . i want to do something like this 
   str("Blah"); // error

  void str(string s) // it works fine ? why ?

Ответы [ 4 ]

0 голосов
/ 23 октября 2019

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

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

0 голосов
/ 23 октября 2019

Когда ваша функция объявлена ​​как

void str(string &s);

Она может быть вызвана только с выражением, которое может быть преобразовано в string&.

Если вы попытаетесь вызвать функцию с помощью

str("Blah");

не работает, поскольку строковый литерал "Blah" не может быть преобразован в std::string&. Временный объект std::string, который компилятор может построить из строкового литерала, может быть преобразован в std::string const& или std::string, но не в std::string&.

0 голосов
/ 23 октября 2019

То, о чем вы спрашивали в обновленном вопросе (передача ссылки на неконстантный std::string объект), не будет (или, по крайней мере, не должно) работать.

Абсолютно верно, чтокомпилятор может создать временный строковый объект из строкового литерала. Этот временный объект может быть передан по значению. Вы также можете привязать ссылку на строковый объект const к временному строковому объекту (и, в более общем случае, ссылку на const T для временного T).

Но ссылка на неконстантный тип может 'не может быть привязан к временному объекту, поэтому компилятор будет (или, по крайней мере, должен) отклонить ваш код.

Однако есть одно исключение: старые компиляторы Microsoft did допускают неконстантную ссылкупривязать к временному объекту. Как отметили некоторые из сотрудников Microsoft, это довольно безопасно - это позволяет вам изменять временный объект, который, как правило, довольно бесполезен (объект будет просто уничтожен, когда функция вернется, поэтому ничто другое не сможет / никогда не увидитизменения, как вы обычно ожидаете, происходят при изменении чего-то, передаваемого по неконстантной ссылке. С другой стороны, они утверждают, что, поскольку ничто иное не может увидеть изменения, разрешение их довольно безвредно. Я склонен не соглашаться споследнее, поскольку допущение того, что происходит, что почти наверняка произошло случайно, вредно не из-за того, что происходит в программе впоследствии, а просто потому, что компилятор не предупредил программиста о том, что он сделал что-то, что почти наверняка является ошибкой.

Я не уверен точно, когда Microsoft исправила этот недостаток в своем компиляторе, но последние версии (по крайней мере, начиная с VS 2015 года) отклоняют код так, как должны. Я знаю, что они приняли его когда-то, ноЯ не уверен насчет точной версии, когда она изменилась.

Сводка

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

0 голосов
/ 23 октября 2019

Это абсолютно нормально. У std :: string есть ctor, который выглядит следующим образом:

string(const char* text);

Таким образом, вызов str("Blah") создаст временный строковый объект (путем вызова вышеуказанного ctor), а затем будет вызван метод str.

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