可能重复:
C++中可为空的值
在C++中表示可为null成员的最佳方式是什么?
在C#中,我们可以使用Nullable<T>
类型。非常需要这样的数据类型,因为并非所有数据都可以具有有意义的值。这是一种非常重要的数据类型,@Jon Skeet花了整整一章的时间,跨越了27页,在他出色的著作《深度C#》中只描述了Nullable<T>
。
一个简单的例子可以是Person
类1,定义为:
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<>
是一个通用的解决方案。但是,例如,如果您的DateTime
是boost::posix_time::ptime
,则已经支持特殊值(例如not_a_date_time
或pos_infin
(-您可以使用这些值。
我参与的每个项目都有某种Fallible
、Maybe
或Nullable
模板类。(实际名称往往反映应用程序首先需要它作为返回值: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。