Почему мы можем возвращать ссылки на переменные-члены класса

Я хочу понять, почему можно вернуть ссылку на переменную члена класса в 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 в некотором не связанном контексте имя не будет найдено.

Но переменная все еще может быть доступна в других контекстах, если вам не требуется искать имя.

Так работают ссылки или указатели. Если вы решили экспортировать адрес своего личного поля, его можно изменить извне.

Это плохая практика, но у языка нет никакого механизма, который бы мешал разработчику делать это.

Другие вопросы по тегам