【问题标题】:Should I store references in classes in c++? [closed]我应该将引用存储在 C++ 中的类中吗? [关闭]
【发布时间】:2023-03-23 00:49:01
【问题描述】:

当我学习 C++ 时,有人告诉我,如果你想让多个类引用同一个对象,你应该给两个类都一个指向该对象的指针。在现代 C++ 中,我可能会将其解释为作为 unique_ptr 的对象和持有非拥有原始指针的类。

最近,我的导师建议您只应在计划将存储指向不同的对象或在某个时候为空时才使用指针。相反,您应该将引用存储在类中。

引用成员变量是我以前从未见过的东西,所以我一直在寻找有关问题的建议......这很有意义......你是说这个引用被假定为永远不会为空...我猜你担心的是你不能 /check/ 为空。它必须是你的类的不变量......

这如何适用于使用多态性的引用?


更新: 我选择的答案很好地涵盖了我的问题,但我想我会为未来的读者澄清一下。我真正想要的是了解使用引用而不是指针作为类成员的后果。我意识到这个问题的措辞听起来更像是我在寻找关于这个想法的意见。

【问题讨论】:

  • 是的,您不能检查 null,但引用也永远不能为 null(除非您非常努力地让它成为 null)。您必须考虑的一件事是引用数据成员必须由类构造函数初始化。你有更具体的问题吗?
  • 你应该更具体一些,这个问题很开放。我想说你的导师说的话很有道理,如果你不打算改变“指针/参考”指向/指的地方,你应该使用参考。这样你就可以在编译时捕获 null 问题。
  • 我一般使用成员 T& 来表示 this 对象的生命周期内的永久关系,并在引用的对象可更改/可为空时使用 T*。
  • “可更改”和“可空”是两个不同的东西。 “使用指针或引用”的困境涉及“可空性”。对于“可变性”,我们使用“const”。

标签: c++ class pointers reference


【解决方案1】:

我应该在 C++ 中的类中存储引用吗?

是的,为什么不呢。这个问题是 IMO '主要基于意见',所以我的回答是基于我自己的经验。

当我不需要指针必须提供的东西时,我使用成员引用,这样我就限制了我的类被错误使用的可能性。这意味着除了绑定新值、分配 nullptr、您不能将指针指向引用、您不能使用引用算术 - 引用中缺少这些功能之外,还有其他可能性。您还应该记住,引用不是对象类型,这意味着如果您将引用作为结构成员,那么它不再是 POD - 即您不能在其上使用 memcpy。

您还应该记住,对于具有非静态引用成员的类,编译器不会生成隐式构造函数。

对我来说,这意味着当类是某种包装器或持有者时,作为变量成员的引用最有用。下面是一个示例,它还显示了使用指针成员类型的替代实现。这种替代实现不会给您带来参考实现的额外好处,并且只会引入未定义的行为。

struct auto_set_false {
   bool& var;
   auto_set_false(bool& v) : var(v) {}
   ~auto_set_false() { var = false; }
};

struct auto_set_false_ptr {
   bool* var;
   auto_set_false_ptr(bool* v) : var(v) {}
   ~auto_set_false_ptr() { *var = false; }
};

int main()
{
    // Here auto_set_false looks quite safe, asf instance will always be
    // able to safely set nval to false. Its harder (but not imposible) to 
    // produce code that would cause Undefined Bahaviour. 
    bool nval = false;
    auto_set_false asf(nval);

    bool* nval2 = new bool(true);
    auto_set_false_ptr asf2(nval2);    
    // lots of code etc. and somewhere in this code a statement like:
    delete nval2;
    // UB
}

【讨论】:

    【解决方案2】:

    在类中存储引用通常不是一个好主意,因为类不能默认构造、复制分配、移动分配,并且成员不能更改(引用不能被反弹)。

    这使得类不可复制。因此,它不能被复制、移动或放置在大多数容器中。更灵活且不那么令人惊讶的解决方案是存储指针或 std::refernce_wrapper。

    【讨论】:

    • 会员可以更改。其他部分有待商榷。仅从某些角度来看,这不是一个好主意。我同意这个类可能不太适合与容器一起使用,但是你提到的 std::reference_wrapper 解决了这个问题。
    • @Andrzej 也许我应该改写/更具体。我的意思是引用不能被反弹。
    【解决方案3】:

    IMO 引用就像指针一样工作。

    唯一的区别在于 dynamic_cast:失败的转换会产生一个带有指针的空指针,并导致抛出一个带有引用的异常。

    【讨论】:

    • 作业呢?和默认构造?
    • @juanchopanza 他们影响多态性?
    • 它们是引用与指针不同的两件事,在决定是否有引用数据成员时必须考虑。
    【解决方案4】:

    由于一个原因,引用比指针好得多:您不必玩空值。 引用不能为空,而且不必检查空值是一个很大的价值。

    小困难是您必须在构造函数中分配引用成员。 但是您以后绝对可以将其更改为指向该类的成员或子类的类的对象的其他非空值。 所以它支持像指针一样的继承。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-21
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 2020-10-08
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多