В чем разница между const string

#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. Это неверно. Несоответствие типов заставляет компилятор создавать временные, и это правило о привязке неконстантных ссылок к временным, которое вызывает ошибку компилятора, а не несоответствие типов.