【问题标题】:How come we can return references to member variables of a class为什么我们可以返回对类的成员变量的引用
【发布时间】:2018-12-02 07:12:22
【问题描述】:

我想了解为什么在 C++ 中可以返回对类成员变量的引用,比如下面的例子:

class Foo
{
int x;
public:
int& get_pvar()
{
return x;
}};

显然我们可以在 main() 中访问变量 x,创建对它的引用,然后更改其内容:

Foo obj;
int& ref = obj.get_pvar();
ref = 7;

但这怎么可能呢? x 没有全局范围,也不是类的静态成员。它被定义在类中。因此,它应该具有本地范围。那么,为什么返回对它的引用甚至在 main() 中创建对它的引用都不是错误呢?

【问题讨论】:

  • 这是完全合法的,而且非常有用。这是大多数运营商的秘诀。没有它你不能x[i]++;
  • 只要obj存在,obj.x也存在,并且可以使用对它的引用。如果obj 不复存在,则obj.x 不复存在,并且使用ref 会产生未定义的行为。

标签: c++ class scope member-variables return-by-reference


【解决方案1】:

您混淆了范围和生命周期。这是两个相关但最终不同的概念。

name x 的范围是类范围。对于类的成员函数(以及其他一些细节,此处不相关),您只能使用非限定名称 x

名为x 的成员对象的生命周期与封闭类对象相同。在这种情况下,obj.x 的生命周期与 obj 相同。由于您在对象的生命周期内返回对对象的引用,因此一切都会检查出来。


您感到困惑的原因可能源于学习了具有自动存储持续时间的对象,如下所示:

{
    int x;
}

将它们的生命周期绑定到它们的词法范围(它们只能在花括号内命名,它们的范围)。但是,虽然对于这些对象来说是正确的,但它并不是普遍适用的。类对象可以独立于其名称范围(如您所见)而存在。有些对象可以有生命周期,但没有范围和名称。考虑:

auto* p = new Foo();

new 表达式创建了一个对象,但它没有名称!所以连说话的余地都没有。这里p 是指针的名称,而不是新创建的对象的名称。

【讨论】:

  • 好的,我想我现在理解得更好了,但是我的问题的第二部分呢:我们如何创建成员变量的引用,outside class ,in main() (即本例中的 ref )以及私有变量的那个?
  • @MrReality - 访问控制,如范围,与名称有关。只有在适当的范围内,您才能访问 names。但是,没有什么能阻止您向另一个范围内的某人提供对您当前有权访问的对象的引用。通过指针或引用的间接访问不会检查名称的可访问性。这些是不相交的。
  • 对不起,我没听懂你的回复。你能简化一下吗?我很困惑我们如何在类之外创建对类的成员变量的引用,即 ref,它不需要使用对象和点运算符。
  • @MrReality - 该成员在物理上位于类对象内。但它是一个普通的旧整数。您可以很好地创建对它的引用。唯一的问题是 int 必须处于活动状态才能使引用有效。现在,您可以在类中引用x,这样您就可以绑定对它的引用,并且可以将该引用返回给调用者。现在调用者有一个对 int 的引用,它是活动的。
【解决方案2】:

“范围”和“访问控制”是适用于名称的东西,而不是变量。说xFoo 中是私有的,意思是如果我们在一些不相关的上下文中写x,就找不到名字。

但如果您不需要查找名称,则仍可以在其他上下文中访问该变量。

【讨论】:

  • 但是变量 x 的生命周期不应该像 get_pvar() 一样结束吗?从我读过的内容来看,它是如何用于普通函数的,这就是为什么我们不能返回对函数局部变量的引用。那么,为什么这不适用于成员函数呢?
  • @MrReality obj.xobj 的成员;只要obj 持续,它就会持续。 obj.x 未在函数中定义。
  • 好的,谢谢。我的问题的第二部分呢:为什么我们可以在 main() 中创建对类外部成员变量的引用,甚至不需要使用对象和点运算符?
  • 如果 x 是 'obj' 的成员,只要 'obj' 还活着,它就会一直活着。在任何情况下,C++ 都不会在变量或成员(或任何其他内存位置)被销毁或取消范围后强制使用它们。
  • @MrReality in obj.get_pvar() 使用了对象和点运算符。如果您愿意,也可以将return x; 视为return (*this).x;
【解决方案3】:

这就是引用或指针的工作方式。如果您决定导出私有字段的地址,则可以从外部进行更改。

这是一种不好的做法,但该语言没有任何机制来阻止开发人员这样做。

【讨论】:

  • 但是成员变量的生命周期不应该在成员函数结束时结束,就像普通函数一样,因为我们不能返回对定义在功能?
猜你喜欢
  • 2020-01-09
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2020-04-15
  • 2018-10-24
相关资源
最近更新 更多