Почему мы можем возвращать ссылки на переменные-члены класса
Я хочу понять, почему можно вернуть ссылку на переменную члена класса в C++, например, в следующем примере:
class Foo
{
int x;
public:
int& get_pvar()
{
return x;
}};
По-видимому, мы можем получить доступ к переменной x в main(), создать ссылку на нее и затем изменить ее содержимое:
Foo obj;
int& ref = obj.get_pvar();
ref = 7;
Но как это возможно? x не имеет глобальной области видимости и не является статическим членом класса. Это определено в классе. Таким образом, он должен иметь локальный охват. Итак, почему не является ошибкой возвращать ссылку на него и даже создавать ссылку на него в main()?
3 ответа
Вы путаете сферу и продолжительность жизни. Это две взаимосвязанные, но в конечном итоге разные концепции.
Объем имени x
это область видимости Вы можете использовать только неквалифицированное имя x
для члена внутри членов функции (и некоторые другие мелочи, не относящиеся к делу) класса.
Время жизни объекта-члена с именем x
такой же, как и вмещающий объект класса. В этом случае время жизни obj.x
такой же как obj
, Так как вы возвращаете ссылку на объект в течение его времени жизни, все проверяется.
Причина вашей путаницы может быть в том, что вы узнали, что объекты с автоматической продолжительностью хранения, например:
{
int x;
}
Их время жизни связано с их лексической областью (они могут быть названы только внутри этих фигурных скобок, их области). Но хотя это верно для этих объектов, это не то, что в целом справедливо. Объекты класса могут жить независимо от области их имени (как вы видели). И некоторые объекты могут иметь время жизни, но не иметь области видимости и имени. Рассматривать:
auto* p = new Foo();
new
выражение создает объект, но у него нет имени! Так что нет никаких оснований даже говорить о. Вот p
это имя указателя, а не вновь созданного объекта.
"Область" и "контроль доступа" - это то, что относится к именам, а не к переменным. Говоря это x
является частным в Foo
означает, что если мы напишем x
в некотором не связанном контексте имя не будет найдено.
Но переменная все еще может быть доступна в других контекстах, если вам не требуется искать имя.
Так работают ссылки или указатели. Если вы решили экспортировать адрес своего личного поля, его можно изменить извне.
Это плохая практика, но у языка нет никакого механизма, который бы мешал разработчику делать это.