C++ 有没有可能;填写「;一个函数参数,默认为空,带有一个对象?

C++ 有没有可能;填写「;一个函数参数,默认为空,带有一个对象?,c++,pass-by-reference,optional-parameters,nullptr,C++,Pass By Reference,Optional Parameters,Nullptr,假设我有这个方法: bool match( /* some optional parameter */ ); 这将进行一些字符串模式匹配,我想允许给它一个可选参数,当方法Match()返回true时,该参数将仅填充已知类型的实例(Match),这样的事情可能吗 在PHP中,我可以执行以下操作: public function match( Match &$match = null ) { if( someMatchingRoutineMatched() ) { $match

假设我有这个方法:

bool match( /* some optional parameter */ );
这将进行一些字符串模式匹配,我想允许给它一个可选参数,当方法
Match()
返回
true
时,该参数将仅填充已知类型的实例(
Match
),这样的事情可能吗

在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
}
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;
  }
}

C++中有类似的可能吗?

我有点让它与下面的工作

bool match( Match*& match ) {
  if( /* something matches */ ) {
    match = new Match;
    return true;
  }

  return false;
}
。。。然后这样称呼它:

// $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
}
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*&”类型的非常量引用无效

不允许使用
Match*&Match=nullptr
,因为对非常量的引用无法绑定到临时变量,并且在此处传递
nullptr
将创建临时
Match*


您可以返回指针,而不是将引用传递给非常量:

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
文档的情况下,很清楚返回的指针是拥有还是不拥有:

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
  }
}
unique_ptr match(){
如果(/*某物匹配*/){
返回make_unique(/*构造函数参数*/);
}
返回空ptr;
}
if(auto m=test.match()){//m被推断为类型unique\u ptr
如果(m!=nullptr){//此处始终为真
//对m做一些有用的事情,然后删除它
//不需要显式删除
}
}

我非常喜欢@zenith建议的c/c++风格,如果一个
nullptr为false,则返回它

但对于记录,这里有另一种选择:

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;
}

不幸的是,来自plain Match()的调用方仍然有可能提前释放内存。因此,我建议使用
唯一\u ptr
共享\u ptr
而不是原始指针指针、指针引用或可选的“输出”参数都是C风格的编码,或者/或者在C++中不是非常地道的。 在没有明确需要的情况下,也不使用动态分配(
新匹配

<>一个C++问题的解决方案,是一个C++习语的实现,有时被称为“错误”。其思想是返回一个包含两个成员变量的对象,一个表示成功,如果第一个为真,则另一个为“真实”返回值

您还可以自己实现一个基本版本,在我们进行此操作时,将指针替换为一个普通实例,因为
Match
听起来不像是一个需要动态分配实例的类[*]

更详细的实现将把它变成一个带有私有成员变量和公共成员函数的类,确保在
success
为false时访问
match
失败:

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()
}
然后,调用者会这样使用它:

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
}


[*]如果您需要动态分配,例如因为<代码>匹配>代码>是多态类层次结构的一部分,那么考虑<代码> STD::UnQuyJPPT < /P> > P>处理这个问题的首选方法可能是返回一个指向创建对象的指针,如果<代码>匹配<代码>成功,或者<代码> 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;
}
#包括
布尔匹配(标准::唯一性测试和测试)
{
bool some_condition=true;
如果(某些条件){
ptr=std::使_唯一();
返回true;
}
其他的
返回false;
}
布尔匹配
{
std::唯一的ptr ptr;
返回匹配(ptr);
}
int main()
{
match();//如果创建了匹配项,它将自动被丢弃
std::唯一的ptr ptr;
如果(匹配(ptr))
{
//用ptr做一些事情
//一旦超出范围,ptr将被删除
}
返回0;
}

有两个重载,一个不带任何内容,另一个与您现有的一样,但没有默认值。@DanMašek好的,这将解决可选位,但当
match()
返回
false
时,是否仍有方法将
match
保持为
null
?基本上,我试图实现的是保证
match
仅在确实找到匹配项时才会填充
match
的实例,否则它将为
null
。我希望这是有意义的。是的,请参见下面的答案。在
C++
PHP
中,您可以返回
NULL
而不是
false
,并返回新对象而不是
true
。如果方法返回的值不是
NULL
,则调用代码可以将其存储到传递给
match()
的变量中。通过这种方式,读者可以清楚地看到