#c #literals #string-literals
#c #литералы #строковые литералы
Вопрос:
Это код из c primer:
string::size_type findChar(const string amp;s, char c, string::size_type amp; occurs){
auto ret = s.size();
occurs = 0;
for (decltype(ret) i = 0; i != s.size(); i){
if (s[i] == c){
if (ret == s.size())
ret = i;
occurs ;
}
}
return ret;
}
int main () {
string::size_type ctr;
cout << findChar("hello, world!", 'o', ctr);
}
Произошла ошибка после удаления const
из const string amp;s
.
ошибка: не удается привязать неконстантную ссылку lvalue типа ‘std::__cxx11::stringamp;’ {иначе ‘std::__cxx11::basic_stringamp;’} к rvalue типа ‘std::__cxx11::string’ {иначе ‘std::basic_string::basic_stringamp;’}__cxx11::basic_string’} cout << findChar(«привет, мир!», ‘o’, ctr);
Интересно, в этом случае, какое поведение компилятора const
изменяет ключевое слово? Спасибо, что помогли мне.
Комментарии:
1. Какая именно ошибка произошла?
2. Удаление
const
означает «этим значением можно манипулировать», что может быть запрещено в зависимости от того, как предоставлен аргумент.3. @nathanpierson я добавил это в вопрос.
4. Вам нужно изучить семантику перемещения c
Ответ №1:
Строковый литерал like "hello, world!"
не является a std::string
. Итак, чтобы вызвать вашу функцию, компилятор должен создать std::string
для вас. Такой объект называется временным. Итак, в первом случае компилятор использует "hello, world!"
для создания a std::string
, а затем привязывает эту временную строку к параметру ссылки s
.
Однако в C есть правило, согласно которому вы не можете привязывать временную ссылку к неконстантной ссылке. Но когда вы переходите s
с const std::stringamp;
на std::stringamp;
, вы просите компилятор сделать именно это. Об этом сообщает вам сообщение об ошибке.
Если вы изменили свой код на этот
string::size_type ctr;
string hello = "hello, world!";
cout << findChar(hello, 'o', ctr);
теперь он будет компилироваться даже без const . Разница здесь в том, что компилятор больше не создает временный std::string
(потому hello
что уже является a std::string
). Таким образом, правило о временных и неконстантных ссылках не применяется.
Ответ №2:
std::string — это класс. const char* — это указатель на память, который, как мы надеемся, содержит строку с нулевым завершением. Вы можете использовать std::string для передачи по значению и создания копий без необходимости вызывать функции, такие как strcpy .
Используйте std::string всякий раз, когда можете, и метод c_str(), когда вам нужен указатель на строку, например, для старых библиотек C.
Комментарии:
1. Все это верно, но, похоже, это не отвечает на заданный вопрос.
Ответ №3:
В вызывающем коде объект, переданный для s
is "hello, world!"
, представляет собой строку, содержимое которой не может быть изменено. В функции findChar
тип const string amp;s
представляет собой ссылку с именем s
на объект типа const string
. Эти два типа совпадают, поэтому компиляция завершается успешно.
Однако параметр string amp;s
обозначает имя, на которое ссылается s
объект типа string
— это изменяемая (изменяемая) строка. Но переданный в argument ( "hello, world!"
) — это строка, которую нельзя изменить. Когда это происходит, компилятор указывает на ошибку несоответствия типов.
Комментарии:
1. Это неверно. Несоответствие типов заставляет компилятор создавать временные, и это правило о привязке неконстантных ссылок к временным, которое вызывает ошибку компилятора, а не несоответствие типов.