说我有这个方法:
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 );
...因为,我相信,引用不允许为空,对吗?
我希望你能看到我想要实现的目标,并且你可以对如何实现我的目标提供一些见解,如果它可以开始的那样,那就是。
答案 0 :(得分:4)
“Match *&”类型的非const引用的无效初始化来自'匹配*'
类型的右值
Match*& match = nullptr
是不允许的,因为对非const的引用无法绑定到临时对象,并且在此处传递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
- 过度拥有指针,因此您不必担心delete
,而且如果不阅读match
的文档就很清楚{1}}返回的指针是拥有还是不拥有:
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
}
}
答案 1 :(得分:3)
指针指针,指针引用或可选&#34; out&#34;在C ++中,参数都是C风格的编码和/或根本不是非常惯用的。
如果不明确需要,也不会使用动态分配(new Match
)。
更像C ++的问题解决方案将是boost::optional
,这是一种C ++习惯用法的实现,有时被称为“#34; Fallible&#34;”。我们的想法是返回一个带有两个成员变量的对象,一个是信号成功,另一个是&#34;真正的&#34;如果第一个为真,则返回值。
您也可以自己实现一个基本版本,当我们使用它时,将指针替换为普通实例,因为Match
听起来不像一个需要动态分配实例的类< SUP> [*]
struct Result
{
bool success;
Match match;
};
更精细的实现会将此变为具有私有成员变量和公共成员函数的类,确保在match
为false时访问success
失败:
class Result
{
public:
bool success() const { return m_success; }
Match match() const {
assert(m_success);
return m_match;
}
Result() : m_success(false), m_match() {}
Result(Match const& match) : m_success(true), m_match(match) {}
private:
bool m_success;
Match m_match;
};
match()
函数本身将如下所示:
Result match()
{
if (someMatchingRoutineMatched()) {
return Result(Match(some_match_arguments));
}
return Result();
}
然后调用者会像这样使用它:
auto const result = match();
if (result.success())
{
// use result.match()
}
如果您向班级添加bool
转换运算符,即:
explicit operator bool() const
{
return m_success;
}
然后您也可以按如下方式编写if
,使其看起来更像您原来的PHP代码,虽然我不认为它更具可读性,我建议不要它:
if (auto const result = match()) {
// use result.match()
} else {
// access to result.match() neither allowed nor needed
}
[*]如果确实需要动态分配,例如因为Match
是多态类层次结构的一部分,那么请考虑std::unique_ptr
。
答案 2 :(得分:1)
如果@zenith提出错误,我非常喜欢返回nullptr
的c / c ++样式。
但是对于记录,这里有另一种选择:
bool match( Match*& match ) {
bool some_condition=true;
if( some_condition ) {
match = new Match;
return true;
}
match = nullptr; // so that you don't need to set it upfront
return false;
}
bool match() { // here if you don't have any pointer to provide
Match *forget_it;
return match(forget_it);
}
但是,有一个弱点,因为如果你总是在免费商店中创建一个新的匹配,你就会泄漏内存。所以匿名版本必须更新:
bool match() {
Match *forget_it;
bool rc=match(forget_it);
delete forget_it; // avoid leaking memory
return rc;
}
不幸的是,仍然可能来自普通Match()的调用者需要释放内存。所以我建议使用unique_ptr<Match>
或shared_ptr<Match>
而不是原始指针。
答案 3 :(得分:1)
处理此问题的首选方法可能是,如果match
成功,则返回指向已创建对象的指针,否则返回nullptr
,如天顶所示。但是如果你想要一些类似于你在PHP中做的事情,我建议如下:
#include <memory>
bool match(std::unique_ptr<Match>& ptr)
{
bool some_condition = true;
if(some_condition) {
ptr = std::make_unique<Match>();
return true;
}
else
return false;
}
bool match()
{
std::unique_ptr<Match> ptr;
return match(ptr);
}
int main()
{
match(); // if Match is created, it's automatically discarded
std::unique_ptr<Match> ptr;
if(match(ptr))
{
// do stuff with ptr
// ptr will be deleted once it goes out of scope
}
return 0;
}