问题描述
在 JavaScript 或 PHP 等动态类型语言中,我经常执行以下功能:
In dynamically typed languages like JavaScript or PHP, I often do functions such as:
function getSomething(name) {
if (content_[name]) return content_[name];
return null; // doesn't exist
}
如果存在则返回一个对象,否则返回null
.
I return an object if it exists or null
if not.
在 C++ 中使用引用的等价物是什么?一般有什么推荐的模式吗?我看到一些框架具有用于此目的的 isNull()
方法:
What would be the equivalent in C++ using references? Is there any recommended pattern in general? I saw some frameworks having an isNull()
method for this purpose:
SomeResource SomeClass::getSomething(std::string name) {
if (content_.find(name) != content_.end()) return content_[name];
SomeResource output; // Create a "null" resource
return output;
}
然后调用者会以这种方式检查资源:
Then the caller would check the resource that way:
SomeResource r = obj.getSomething("something");
if (!r.isNull()) {
// OK
} else {
// NOT OK
}
然而,必须为每个类实现这种神奇的方法似乎很繁重.此外,当对象的内部状态应该从null"设置为not null"时,似乎也不明显.
However, having to implement this kind of magic method for each class seems heavy. Also it doesn't seem obvious when the internal state of the object should be set from "null" to "not null".
这个模式有什么替代方案吗?我已经知道它可以使用指针来完成,但我想知道如何/是否可以使用引用来完成.或者我应该放弃在 C++ 中返回空"对象并使用一些 C++ 特定的模式?任何有关正确方法的建议将不胜感激.
Is there any alternative to this pattern? I already know it can be done using pointers, but I am wondering how/if it can be done with references. Or should I give up on returning "null" objects in C++ and use some C++-specific pattern? Any suggestion on the proper way to do that would be appreciated.
推荐答案
你不能在引用期间这样做,因为它们永远不应该是 NULL.基本上有三种选择,一种使用指针,另一种使用值语义.
You cannot do this during references, as they should never be NULL. There are basically three options, one using a pointer, the others using value semantics.
使用指针(注意:这要求资源在调用者有指向它的指针时不会被破坏;还要确保调用者知道它不需要删除对象):>
SomeResource* SomeClass::getSomething(std::string name) {
std::map<std::string, SomeResource>::iterator it = content_.find(name);
if (it != content_.end())
return &(*it);
return NULL;
}
使用带有 bool
的 std::pair
来指示该项目是否有效(注意:要求 SomeResource 具有适当的默认构造函数并且是建造成本不高):
Using std::pair
with a bool
to indicate if the item is valid or not (note: requires that SomeResource has an appropriate default constructor and is not expensive to construct):
std::pair<SomeResource, bool> SomeClass::getSomething(std::string name) {
std::map<std::string, SomeResource>::iterator it = content_.find(name);
if (it != content_.end())
return std::make_pair(*it, true);
return std::make_pair(SomeResource(), false);
}
使用boost::optional代码>:
boost::optional<SomeResource> SomeClass::getSomething(std::string name) {
std::map<std::string, SomeResource>::iterator it = content_.find(name);
if (it != content_.end())
return *it;
return boost::optional<SomeResource>();
}
如果你想要值语义并且有能力使用 Boost,我推荐选项三.boost::optional
相对于 std::pair
的主要优点是一个单元化的 boost::optional
值不会构造它的类型封装.这意味着它适用于没有默认构造函数的类型,并为具有非平凡默认构造函数的类型节省时间/内存.
If you want value semantics and have the ability to use Boost, I'd recommend option three. The primary advantage of boost::optional
over std::pair
is that an unitialized boost::optional
value doesn't construct the type its encapsulating. This means it works for types that have no default constructor and saves time/memory for types with a non-trivial default constructor.
我还修改了您的示例,因此您不会两次搜索地图(通过重复使用迭代器).
I also modified your example so you're not searching the map twice (by reusing the iterator).
这篇关于返回“NULL 引用"在 C++ 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!