Это код из учебника С++:
string::size_type findChar(const string &s, char c, string::size_type & 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 &s
.
ошибка: невозможно связать неконстантную ссылку lvalue типа 'std::__cxx11::string&' {aka 'std::__cxx11::basic_string&'} с rvalue типа 'std::__cxx11::string' {aka 'std ::__cxx11::basic_string'} cout << findChar ("привет, мир!", 'o', ctr);
Интересно, в этом случае какое поведение компилятора меняет ключевое слово const
? Спасибо за помощь.
Удаление const
означает, что «этим значением можно манипулировать», что может быть запрещено в зависимости от того, как предоставлен аргумент.
@nathanpierson Я добавил это в вопрос.
Вам нужно изучить семантику перемещения С++
std::string — это класс. const char* — это указатель на память, которая, как мы надеемся, содержит строку с завершающим нулем. Вы можете использовать std::string для передачи по значению и создания копий без вызова таких функций, как strcpy.
Используйте std::string везде, где это возможно, и метод c_str(), когда вам нужен указатель на строку, например, для старых библиотек C.
Все это верно, но, кажется, не отвечает на заданный вопрос.
Строковый литерал вроде "hello, world!"
не является std::string
. Поэтому, чтобы вызвать вашу функцию, компилятор должен создать для вас std::string
. Такой объект называется временным. Таким образом, в первом случае компилятор использует "hello, world!"
для создания std::string
, а затем привязывает эту временную строку к ссылочному параметру s
.
Однако в C++ есть правило, согласно которому вы не можете привязать временную ссылку к неконстантной ссылке. Но когда вы меняете s
с const std::string&
на std::string&
, вы просите компилятор сделать именно это. Это то, что сообщение об ошибке говорит вам.
Если вы изменили свой код на этот
string::size_type ctr;
string hello = "hello, world!";
cout << findChar(hello, 'o', ctr);
теперь он будет компилироваться даже без const. Разница здесь в том, что компилятор больше не создает временный std::string
(потому что hello
уже является std::string
). Таким образом, правило о временных и неконстантных ссылках не применяется.
В вызывающем коде для s
передается объект "hello, world!"
, представляющий собой строку, содержимое которой нельзя изменить. В функции findChar
тип const string &s
является ссылкой с именем s
на объект типа const string
. Эти два типа совпадают, поэтому компиляция завершается успешно.
Однако параметр string &s
обозначает ссылку с именем s
на объект типа string
— это изменяемая (изменяемая) строка. Но переданный аргумент ("hello, world!"
) — это строка, которую нельзя изменить. Когда это происходит, компилятор указывает на ошибку несоответствия типов.
Это неправда. Несоответствие типов приводит к тому, что компилятор создает временные объекты, а правило о привязке неконстантных ссылок к временным объектам вызывает ошибку компилятора, а не несоответствие типов.
Какая именно ошибка произошла?