说我有这种方法:
bool match( /* some optional parameter */ );
它将执行一些字符串模式匹配,我想允许给它一个可选参数,该方法仅在方法
Match
返回match()
时填充一个已知类型(true
)的实例,这样可能吗?在PHP中,我可以这样做:
public function match( Match &$match = null ) {
if( someMatchingRoutineMatched() ) {
$match = new Match();
return true;
}
return false; // $match will stay null
}
然后这样称呼它:
// $test is some instance of the class that implements match()
// I don't have to declare $m up front, since it will be filled by reference
if( $test->match( $m ) ) {
// $m would be filled with an instance of Match
}
else {
// $m would be null
}
在c++中是否可能有类似的东西?
我有点理解它可以与以下内容一起使用
bool match( Match*& match ) {
if( /* something matches */ ) {
match = new Match;
return true;
}
return false;
}
...然后像这样调用它:
Match* m = nullptr; // I wish I wouldn't have to declare this upfront as a nullptr
if( test.match( m ) ) {
// a match occured, so m should no longer be a null pointer
// but let's just make sure
if( m != nullptr ) {
// do something useful with m and afterwards delete it
delete m;
}
}
...但是,这一切都有点麻烦。此外,我似乎不允许将参数设为可选,例如:
bool match( Match*& match = nullptr );
...因为我相信引用不允许为空,对吗?
希望您能看到我正在努力实现的目标,并且如果可以的话,也可以给我一些如何实现目标的见识。
最佳答案
不允许使用Match*& match = nullptr
,因为对非const的引用无法绑定(bind)到临时对象,并且在此处传递nullptr
会创建一个临时的Match*
。
您可以返回指针,而不是传递对非const的引用:
Match* match() {
if( /* something matches */ ) {
return new Match;
}
return nullptr;
}
现在,
nullptr
返回值表示没有匹配项,而非nullptr
表示已找到匹配项:if( Match* m = test.match() ) { // nullptr means false, non-nullptr means true
if( m != nullptr ) { // always true here
// do something useful with m and afterwards delete it
delete m;
}
}
或者您可以使用@DanMašek提到的重载:
bool match() {
Match* m = nullptr;
bool result = match(m);
delete m; // deleting a nullptr is a no-op
return result;
}
最后但并非最不重要的一点是,强制使用
unique_ptr
-over-raw-owning-pointer,因此您不必担心delete
,并且无需阅读match
文档就可以清楚地知道返回的指针是拥有还是不拥有:unique_ptr<Match> match() {
if( /* something matches */ ) {
return make_unique<Match>( /* constructor arguments */ );
}
return nullptr;
}
if( auto m = test.match() ) { // m deduced to be of type unique_ptr<Match>
if( m != nullptr ) { // always true here
// do something useful with m and afterwards delete it
// no need to delete explicitly
}
}