lau*_*ent 41 c++ methods null design-patterns object
在动态类型语言(如JavaScript或PHP)中,我经常执行以下功能:
function getSomething(name) {
if (content_[name]) return content_[name];
return null; // doesn't exist
}
Run Code Online (Sandbox Code Playgroud)
我返回一个对象,如果它存在或null不存在.
使用引用的C++中的等价物是什么?一般有推荐的模式吗?我看到一些框架有一个isNull()用于此目的的方法:
SomeResource SomeClass::getSomething(std::string name) {
if (content_.find(name) != content_.end()) return content_[name];
SomeResource output; // Create a "null" resource
return output;
}
Run Code Online (Sandbox Code Playgroud)
然后调用者将检查资源:
SomeResource r = obj.getSomething("something");
if (!r.isNull()) {
// OK
} else {
// NOT OK
}
Run Code Online (Sandbox Code Playgroud)
然而,必须为每个类实现这种魔术方法似乎很重.当对象的内部状态应该从"null"设置为"not null"时,似乎并不明显.
这种模式还有其他选择吗?我已经知道它可以使用指针完成,但我想知道如何/如果它可以用引用完成.或者我应该放弃在C++中返回"null"对象并使用一些特定于C++的模式?任何有关正确方法的建议都将受到赞赏.
Sve*_*ven 45
您不能在引用期间执行此操作,因为它们永远不应为NULL.基本上有三个选项,一个使用指针,另一个使用值语义.
使用指针(注意:这要求在调用者具有指向它的指针时不会破坏资源;还要确保调用者知道它不需要删除对象):
SomeResource* SomeClass::getSomething(std::string name) {
std::map<std::string, SomeResource>::iterator it = content_.find(name);
if (it != content_.end())
return &(*it);
return NULL;
}
Run Code Online (Sandbox Code Playgroud)使用std::paira bool来指示项是否有效(注意:要求SomeResource具有适当的默认构造函数并且构造起来并不昂贵):
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);
}
Run Code Online (Sandbox Code Playgroud)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>();
}
Run Code Online (Sandbox Code Playgroud)如果你想要价值语义并且能够使用Boost,我建议选择三.boost::optional过度的主要优点std::pair是,单元化boost::optional值不构造其封装类型.这意味着它适用于没有默认构造函数的类型,并为具有非平凡构造函数的类型节省时间/内存.
我还修改了你的例子,因此你没有两次搜索地图(通过重用迭代器).
jal*_*alf 26
为什么"除了使用指针"?使用指针是你在C++中的方式.除非你定义一些"可选"类型,它类似于isNull()你提到的功能.(或使用现有的,像boost::optional)
参考资料的设计和保证永远不会为空.问"所以如何让它们为空"是荒谬的.当您需要"可空引用"时,可以使用指针.
如果为所有类型实现特殊方法,那么一个很好且相对非侵入性的方法可以避免这个问题,它与boost.optional一起使用.它本质上是一个模板包装器,允许您检查保持的值是否"有效".
顺便说一句,我认为这是在文档很好的解释,但要注意boost::optional的bool,这是一个建筑,这是很难解释的.
编辑:问题询问"NULL引用",但代码片段有一个按值返回的函数.如果该函数确实返回了一个引用:
const someResource& getSomething(const std::string& name) const ; // and possibly non-const version
Run Code Online (Sandbox Code Playgroud)
那么这个函数只有在someResource被引用的生命周期至少与返回引用的对象的生命周期一样长时才有意义(否则你将会有一个悬空引用).在这种情况下,返回指针似乎完全没问题:
const someResource* getSomething(const std::string& name) const; // and possibly non-const version
Run Code Online (Sandbox Code Playgroud)
但是你必须绝对清楚地表明调用者没有获得指针的所有权,不应该尝试删除它.
我可以想到几种方法来解决这个问题:
boost::optional