在C++中表示可为null成员的最佳方式



可能重复:
C++中可为空的值

在C++中表示可为null成员的最佳方式是什么?

在C#中,我们可以使用Nullable<T>类型。非常需要这样的数据类型,因为并非所有数据都可以具有有意义的值。这是一种非常重要的数据类型,@Jon Skeet花了整整一章的时间,跨越了27页,在他出色的著作《深度C#》中只描述了Nullable<T>

一个简单的例子可以是Person1,定义为:

struct Person
{
  std::string Name;
  DateTime    Birth;
  DateTime    Death;
  //...
};

由于一个人总是有生日,所以上述类别的Birth成员总是会有一些有意义的值。但是Death呢?如果这个人还活着,它应该有什么价值?在C#中,该成员可以声明为Nullable<DataTime>2,如果该人还活着,则可以将其分配为null

在C++中,解决这个问题的最佳方法是什么?到目前为止,我只想到一个解决方案:将成员声明为指针

 DataTime *Death;

现在,当人活着时,它的值可以是nullptr。但它强制对死者使用new,因为它将具有一些有效值。这反过来意味着不能依赖编译器生成的默认副本语义代码。程序员必须按照第三条规则(C++03(编写复制构造函数、复制赋值、析构函数,或者在C++11中编写第五条规则。

那么,对于这个问题,我们有什么比让它成为指针更好、更优雅的解决方案吗?


1.其他例子包括关系数据库表,因为在许多DBMS中,列可以为null

2.这也有一个简写。可以写入与CCD_ 11完全相同的的CCD_

您可以查看Boost。可选:

struct Person
{
  std::string               Name;
  DateTime                  Birth;
  boost::optional<DateTime> Death;
  //...
};
  • 您的Death一开始是"未初始化"的
  • 然后可以使用=为其指定一个值,如Death = myDateTime
  • 当使用Death.is_initialized()时,可以使用Death.get()
  • Death.reset()重新初始化

然而,对于像这样的简单情况,通常认为只选择自己的公然哨兵值更连贯,比如DateTime为"0000-00-00 00:00:00"。

取决于DateTime——就像@Tomalak在他的回答中所说的,boost::optional<>是一个通用的解决方案。但是,例如,如果您的DateTimeboost::posix_time::ptime,则已经支持特殊值(例如not_a_date_timepos_infin(-您可以使用这些值。

我参与的每个项目都有某种FallibleMaybeNullable模板类。(实际名称往往反映应用程序首先需要它作为返回值:CCD_ 28,Nullable为数据库建模等(引入CCD_ 30;遗憾的是,他们使用隐式转换而不是isValid(命名(函数,这会显著地导致可读性较差的代码(到了我会避免的程度,除了可能实现我自己的Maybe(。

由于死亡不太可能发生在出生前的任何时间,您也可以在最初将其设置为出生-1,并在实际事件中更改。在更常见的术语中,您可能会将birth-1称为sentinel值或占位符值。您也可以选择一个足够低的常数值,以免被误认为是真实值,但前提是您对数据有一定的了解。

你可以做之前众多程序员所做的事情!使用特定值作为"不存在"。。。例如,我听说"2000年1月1日"很常见:-(:-(出于互操作性的原因,你可以使用"2038年1月19日03:14:07 UTC":-((如果不清楚的话,这是个笑话。我指的是Y2K问题和Y2038问题。我展示了使用"特殊"日期作为状态的问题…类似11-11-11和类似的事情(

DataTime的最大/最小值可能更正确:-(它仍然是错误的,因为您将"状态"与"值"混合在一起。最好在C++中重建Nullable类型(最后这很容易:一个模板化的类,带有用于null/not null的bool和T字段(

我会创建一个表示null值的静态成员,然后将死亡日期的地址与静态对象的地址进行比较。如果它们相等,则值为NULL。

最新更新