在 C++ 中表示 Nullable 成员的最佳方式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7645578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to represent Nullable member in C++?
提问by Nawaz
Possible Duplicate:
Nullable values in C++
可能的重复:
C++ 中的可空值
What is the best way to represent nullable member in C++?
在 C++ 中表示可空成员的最佳方式是什么?
In C#, we can use Nullable<T>
type. Such a data type is very much needed as not everything can have meaningfulvalue. It is so important data type that @Jon Skeethas spent one entire chapter, spanned over 27 pages, describing only Nullable<T>
in his outstanding book C# in Depth.
在 C# 中,我们可以使用Nullable<T>
类型。非常需要这种数据类型,因为并非所有东西都具有有意义的价值。这是非常重要的数据类型,@Jon Skeet花了一整章,跨越 27 页,仅Nullable<T>
在他的杰出著作C# in Depth 中进行了描述。
One simple example can be a Person
class1, defined as:
一个简单的例子可以是Person
类1,定义为:
struct Person
{
std::string Name;
DateTime Birth;
DateTime Death;
//...
};
As a person always have birthdate, so the Birth
member of the above class will always have some meaningfulvalue. But how about Death
? What should it value be if the person is alive? In C#, this member can be declared as Nullable<DataTime>
2which can be assigned with null
if the person is alive.
作为一个人总是有生日的,所以Birth
上面的类的成员总是会有一些有意义的价值。但是Death
呢?如果这个人还活着,它的价值应该是多少?在 C# 中,可以将此成员声明为Nullable<DataTime>
2,null
如果此人还活着,则可以将其赋值。
In C++, what is the best way to solve this? As of now, I've only one solution in mind: declare the member as pointer:
在 C++ 中,解决这个问题的最佳方法是什么?到目前为止,我只有一个解决方案:将成员声明为指针:
DataTime *Death;
Now its value can be nullptr
when the person is alive. But it forces the use of new
for dead person, as it's going to have some valid value. It in turn implies one cannot rely on the defaultcopy-semantic code generated by the compiler. The programmer has to write copy-constructor, copy-assignment, destructor following rule of three(C++03), Or in C++11, rule of five.
现在它的价值可以是nullptr
人活着的时候。但它强制使用new
for dead person,因为它会有一些有效的价值。这反过来意味着不能依赖编译器生成的默认复制语义代码。程序员必须按照三规则(C++03)编写复制构造函数,复制赋值,析构函数,或者在 C++11 中,五规则。
So do we have any better, elegant solution to this problem than just making it pointer?
那么对于这个问题,除了让它成为指针之外,我们还有更好、更优雅的解决方案吗?
1. Other examples include relational database tables, as in many DBMSs columns can be nullable.
1. 其他示例包括关系数据库表,因为在许多 DBMS 中,列可以为空。
2. There is also a shorthand for this. One can write DataTime?
which is exactlysame as Nullable<DateTime>
.
2. 这也有一个简写。人们可以写DataTime?
这正是因为相同Nullable<DateTime>
。
回答by Lightness Races in Orbit
You could look into Boost.Optional:
你可以看看Boost.Optional:
struct Person
{
std::string Name;
DateTime Birth;
boost::optional<DateTime> Death;
//...
};
- Your
Death
is "uninitialised" at first. - You can then assign a value to it with
=
, likeDeath = myDateTime
. - When
Death.is_initialized()
, you can useDeath.get()
. - Uninitialise it again with
Death.reset()
.
- 你一开始
Death
是“未初始化的”。 - 然后,您可以使用 为它分配一个值
=
,例如Death = myDateTime
。 - 时
Death.is_initialized()
,您可以使用Death.get()
. - 再次取消初始化它
Death.reset()
。
For simple cases like this, though, it's usually considered more coherent to just pick your own blatant sentinel value like, say, a DateTime
of "0000-00-00 00:00:00".
但是,对于像这样的简单情况,通常认为只选择您自己的明显标记值(例如DateTime
“0000-00-00 00:00:00”)会更加连贯。
回答by Nim
Depends on DateTime
- like @Tomalak says in his answer, boost::optional<>
is a generic solution. However if for example your DateTime
is a boost::posix_time::ptime
, then there is already support for special values(for example not_a_date_time
or pos_infin
) - you could use these.
取决于DateTime
- 就像@Tomalak 在他的回答中所说,boost::optional<>
是一个通用的解决方案。但是,如果例如您DateTime
是 a boost::posix_time::ptime
,那么已经支持特殊值(例如not_a_date_time
或pos_infin
) - 您可以使用这些。
回答by James Kanze
Every project I've worked on has had some sort of Fallible
, Maybe
or
Nullable
template class. (The actual name tends to reflect what the
application first needed it for: Fallible
as a return value,
Nullable
to model databases, etc.). More recently, Boost has
introduced boost::optional
; regretfully, they use implicit conversions
instead of an isValid
(named) function, which results in noticeably
less readable code (to the point where I'd avoid it, except maybe to
implement my own Maybe
).
我参与过的每个项目都有某种Fallible
,Maybe
或
Nullable
模板类。(实际名称往往反映了应用程序最初需要它的用途:Fallible
作为返回值、
Nullable
对数据库进行建模等)。最近,Boost 引入了boost::optional
; 遗憾的是,他们使用隐式转换而不是isValid
(命名)函数,这导致代码的可读性明显降低(以至于我会避免它,除非可能实现我自己的Maybe
)。
回答by xanatos
You can do what legions of programmers did before you! Use a specific value as "not present"... For example I've heard that "1 Jan 2000" was pretty common :-) :-) For interoperability reasons you could use "19 Jan 2038 03:14:07 UTC" :-) :-) (it's a joke, if it isn't clear. I'm referencing the Y2K problem and the Y2038 problem. I'm showing the problem of using "special" dates as states... Things like 11-11-11 and similar)
您可以做之前众多程序员所做的事情!使用特定值作为“不存在”...例如,我听说“1 Jan 2000”很常见:-) :-) 出于互操作性原因,您可以使用“19 Jan 2038 03:14:07 UTC” :-) :-) (这是个笑话,如果不清楚的话。我指的是 Y2K 问题和 Y2038 问题。我正在展示使用“特殊”日期作为状态的问题......像 11 这样的问题-11-11 和类似的)
The maximum/minimum value of your DataTime
is probably more correct :-) And it's still wrong, because you are mixing a "state" with a "value". Better that you rebuild the Nullable
type in C++ (in the end it's quite easy: a templated class with a bool for null/not null and the T field)
您的最大值/最小值DataTime
可能更正确:-) 而且它仍然是错误的,因为您将“状态”与“值”混合在一起。最好Nullable
在 C++ 中重建类型(最后它很容易:一个带有布尔值的模板化类,用于 null/not null 和 T 字段)
回答by mtijn
as death is particularly unlikely to be any time beforebirth you could just as well set it to birth - 1 initially and have it changed on the actual event. in more common terms you'd probably call birth - 1 a sentinel value or placeholder value. you could also pick a constant value low enough not to be mistaken for a real value, but that assumes you have some knowledge of your data.
由于死亡特别不可能发生在出生前的任何时间,您也可以将其设置为出生 - 1 最初并在实际事件中更改。在更常见的术语中,您可能会称出生 - 1 为哨兵值或占位符值。您也可以选择一个足够低的常数值,以免被误认为是真实值,但前提是您对数据有一定的了解。
回答by WebMonster
I would create a static member which represent null value, than compare the address of date of death to the address of the static object. If they are equal the value is NULL.
我会创建一个表示空值的静态成员,然后将死亡日期的地址与静态对象的地址进行比较。如果它们相等,则值为 NULL。