什么时候最好将数据成员存储为引用而不是指针?

问题描述 投票:9回答:5

假设我有一个包含数据库连接数据成员的对象Employee_Storage。该数据成员是应该存储为指针还是作为引用?

  • 如果我将它存储为参考,我不必进行任何NULL检查。 (无论如何,NULL检查有多重要?)
  • 如果我将它存储为指针,则更容易设置Employee_Storage(或MockEmployee_Storage)以进行测试。

一般来说,我一直习惯于将我的数据成员存储为引用。但是,这使我的模拟对象难以设置,因为我现在必须传入true / mock对象,而不是能够传入NULLs(大概是在默认构造函数中)。

是否有一个很好的经验法则,特别是关注可测试性?

c++ tdd reference mocking pointers
5个回答
14
投票

如果在构造中分配引用作为数据成员,那么它最好是存储的,并且没有理由不改变它们。由于无法重新分配引用,因此它们非常有限。

通常,我通常存储为指针(或某种形式的模板化智能指针)。这更加灵活 - 既可用于测试(如您所述),也可用于正常使用。


8
投票

将引用存储为数据成员几乎从不优先,并且很多时候它是不可能的。如果对象必须是可分配的(因为它们必须存储在标准库容器中),则不能使用引用。此外,无法重新引用引用,因此一旦使用对象初始化引用,就不能使引用引用不同的对象。

有关该问题的更详细讨论,请参阅此问题Should I prefer pointers or references in member data?


3
投票

我试图自己解决这个问题,所以不妨发布它。我得出结论,使用引用数据成员似乎不是一个好主意,因为在初始化它时可能会无意中创建别名。

#include <iostream>
using namespace std;
class stuff
{
public:
explicit stuff(int &a):x(a) //you have to initialize it here
{
//body intialization won't work
};
int& x; //reference data member
};

int main()
{
int A=100; 
stuff B(A);//intialize B.x
cout<<B.x<<endl;//outputs 100
A=50;//change A;
cout<<B.x<<endl; //outputs 50, so B.x is an alias of A.
system("pause");
return 0;
}

2
投票

如果有选择,我喜欢尽可能使用最受约束的类型。因此,如果我不需要支持null对象,我更愿意声明一个

Foo& m_foo;

成员而不是成员

Foo*const m_foo;

成员,因为前一个声明记录了m_foo不能为空的事实。从短期来看,优势并不是那么好。但是从长远来看,当你回到旧代码时,你不必担心m_foo为空的情况的即时保证是非常有价值的。

还有其他方法可以达到类似的效果。我在他们不理解引用的地方工作的一个项目会坚持任何潜在的空指针后缀为'00',例如m_foo00。有趣的是,boost::optional似乎support references虽然我还没有尝试过。或者您可以使用断言来丢弃代码。


0
投票

添加到这个问题..

具有参考数据成员的类:

  • 你必须在构造时将值传递给对象(不出意外)
  • 打破封装规则,因为引用变量可以从外部类更改,而没有类对象可以控制它。 (我认为唯一的用例可能是这样的,但出于一些非常专业的原因。)
  • 阻止创建赋值运算符。你要复制什么?
  • 您需要确保在对象处于活动状态时不会销毁引用的变量
© www.soinside.com 2019 - 2024. All rights reserved.