#include
#include
using namespace std;
const auto get_str() {
string s = "hello";
return move(s);
}
int main ()
{
auto a = get_str();
cout << a << '\n';
auto& b = get_str();
cout << b << '\n';
const auto c = get_str();
cout << c << '\n';
const auto& d = get_str();
cout << d << '\n';
string e = get_str();
cout << e << '\n';
const string f = get_str();
cout << f << '\n';
const string& g = get_str();
cout << g << '\n';
string& h = a;
cout << h << '\n';
string& i = e;
cout << i << '\n';
}
string& s = string("hello"); // недопустимая инициализация
const string& cs = string("hello"); // допустимая инициализация
const string& cch = "hello"; // допустимая инициализация
В первом случае ссылка не константная, а следовательно по ней допускается изменять значение, но переменной как таковой нет, что приведёт к ошибке компиляции. По сути это анонимный адрес на строковый литерал. А инициализировать константные ссылки можно, потому как анонимный объект не предполагается изменять. Это позволяет при передаче параметров в функции и методы избежать затрат на копирование, а также создавать временные объекты.
Ну и правила:
- lvalue, могут быть преобразованы в rvalue, если они не являются массивом, функцией и не имеют неполный тип.
- rvalue в lvalue преобразовать не допускается, то есть везде где ожидается lvalue можно присвоить только lvalue
string get_str() {
string s = "hello";
return s;
}
int main () {
...
string const& a = get_str (); // (1)
string& b = get_str (); // Ошибка! (2)
...
}
И не понял, почему вызов функции работает в случае (1).
В случае (2) понятно, что мы пытаемся сделать ссылку b на содержимое переменной s, которое сразу же очищается после завершения функции, поэтому мы делаем ссылку на несуществующую область памяти, отсюда и ошибка.
Но как эту проблему решает константная ссылка?
Вычитал, что "константная ссылка продлевает время жизни", но я не могу понять как и какой у этого механизм в данном случае?