c 11 — инициализировать std::string из char * непосредственно с помощью {} конструктора

#c #string #c 11 #curly-braces

#c #строка #c 11 #фигурные скобки

Вопрос:

У меня есть функция, которая принимает std::stringamp; :

 void f(std::stringamp; s) { ... }
  

У меня есть const char* который должен быть входным параметром для этой функции. Это работает:

 const char* s1 = "test";
std::string s2{s};
f(s2);
  

Это не:

 const char* s1 = "test";
f({s1});
  

Почему это невозможно? Забавно то, что CLion IDE не жалуется, но компилятор:

 no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘std::basic_string<char>amp;’
  

Комментарии:

1. Почему вы ожидаете, что это сработает?

2. Функция ожидает строку по ссылке, а ваш второй вариант этого не делает. Однако в вашем первом примере s1 это совершенно не нужно, учитывая ваш пример: std::string s2 = "test";

3. Забавно то, что CLion IDE не жалуется, но компилятор: — CLion не является компилятором. Компилятор выигрывает.

4. Если вы подумаете, что это const char* не std::string так, то для того, чтобы это вообще работало, для передачи в функцию потребуется создать новую временную строку. Но функция изменяет передаваемую вами строку!! Поэтому он не примет временный. Неконстантная ссылка не будет привязываться к временным файлам.

5. Если вам нужна неконстантная ссылка, вы все равно не сможете передать временную.

Ответ №1:

Это не имеет ничего общего с построением std::string из char const* .

f ожидает значение lvalue для строки, и, создавая временный экземпляр на месте, вы предоставляете значение rvalue, которое не может быть привязано к неконстантной ссылке lvalue. f(string{}) так же недопустимо.

Комментарии:

1. Ну, f ожидает значение lvalue . Использование ссылочного параметра lvalue — это способ, которым вы выражаете это в C , но это не означает, что «f ожидает ссылку».

2. @KerrekSB Я не уверен, что понимаю. Я думал, что функция ожидает ссылку на значение lvalue, и если вы передаете значение lvalue, ссылка привязывается к нему.

3. На самом деле вы не можете «ожидать ссылку». Функции вызываются с аргументами, аргументами являются выражения, а выражения никогда не являются ссылками. Важно то, что выражение является значением lvalue. Ссылки — это способ рассказать о значениях lvalues.

4. @KerrekSB Хорошо, я изменил формулировку, теперь лучше? Мне придется самому разобраться в этом.

5. Мм, не совсем. Значения ни на что не «ссылаются». Дело в том, что «f ожидает значение lvalue std::string » или, может быть, «значение строки lvalue». Я не знаю лучшего или более простого способа сказать это. Значение lvalue — это просто определенный вид значения.

Ответ №2:

Ваша функция получает неконстантную ссылку, и вы передаете временный объект, для которого требуется копия или параметр ссылки const. Два решения: создать другую функцию для получения объекта в качестве ссылки на rvalue и вызвать другую перегрузку внутри

 void f(stringamp;amp; s) {  f(s); } 
  

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

 void f(const std::stringamp; s) { ... }
  

Ответ №3:

Один из вариантов — изменить вашу функцию, чтобы она принимала строку по значению, а не по ссылке. Тогда это сработает. В любом случае, в C 11 иногда предпочтительнее передавать по значению, а не по ссылке.