97

私は C++ にかなり慣れていないので、学習中は多くの Java イズムを使用して設計する傾向があります。Tとにかく、Java では、特定のパラメーターに一致するからオブジェクトを返す「検索」メソッドを持つクラスがCollection< T >あれば、そのオブジェクトを返し、オブジェクトがコレクションに見つからない場合は を返しnullます。次に、呼び出し関数で確認しますif(tResult != null) { ... }

nullC++ では、オブジェクトが存在しない場合は値を返せないことがわかりました。オブジェクトが見つからなかったことを呼び出し元の関数に通知する T 型の「インジケーター」を返したいだけです。実際には例外的な状況ではないため、例外をスローしたくありません。

これは私のコードが今どのように見えるかです:

class Node {
    Attr& getAttribute(const string& attribute_name) const {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return NULL; // what should this be?
    }

private:
    vector<Attr> attributes;
}

そのようなマーカーを付けることができるようにするにはどうすれば変更できますか?

4

9 に答える 9

73

C++ では、参照を null にすることはできません。何も見つからない場合にオプションで null を返したい場合は、参照ではなくポインターを返す必要があります。

Attr *getAttribute(const string& attribute_name) const {
   //search collection
   //if found at i
        return &attributes[i];
   //if not found
        return nullptr;
}

それ以外の場合、参照によって返すことを主張する場合は、属性が見つからない場合に例外をスローする必要があります。

(ちなみに、あなたのメソッドがconstconst属性であり、それを返すことについて少し心配しています。哲学的な理由から、 を返すことをお勧めしconst Attr *ます。この属性も変更したい場合は、非constメソッドでオーバーロードできます。非const属性も返します。)

于 2010-04-14T16:44:08.820 に答える
56

ここにはいくつかの可能な答えがあります。存在する可能性のあるものを返したいとします。以下にいくつかのオプションを示します。最も好ましくないものから最も好ましいものまであります。

  • 参照によって戻り、例外によって見つけることができないというシグナル。

    Attr& getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            throw no_such_attribute_error;
    }

属性が見つからないことは実行の通常の部分である可能性が高いため、それほど例外的ではありません。これの処理はうるさいでしょう。null 参照を持つことは未定義の動作であるため、null 値を返すことはできません。

  • ポインタで戻る

    Attr* getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return &attributes[i];
       //if not found
            return nullptr;
    }

getAttribute からの結果が非 NULL ポインターになるかどうかを確認するのを忘れがちで、バグの原因になりやすいです。

  • Boost.Optionalを使用する

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return boost::optional<Attr&>();
    }

boost::optional は、ここで何が起こっているかを正確に示し、そのような属性が見つかったかどうかを調べるための簡単な方法を備えています。


補足: std::optional は最近 C++17 に投票されたので、これは近い将来「標準」になるでしょう。

于 2010-04-14T16:57:20.097 に答える
22

NULL 戻り値を表す静的オブジェクトを簡単に作成できます。

class Attr;
extern Attr AttrNull;

class Node { 
.... 

Attr& getAttribute(const string& attribute_name) const { 
   //search collection 
   //if found at i 
        return attributes[i]; 
   //if not found 
        return AttrNull; 
} 

bool IsNull(const Attr& test) const {
    return &test == &AttrNull;
}

 private: 
   vector<Attr> attributes; 
};

そしてソースファイルのどこかに:

static Attr AttrNull;
于 2010-04-14T17:06:11.933 に答える
3

NULL戻り値が必要な場合は、参照の代わりにポインターを使用する必要があります。

参照自体を にすることはできませんNULL

(将来のコメント投稿者への注意:はい、本当にしようとすれば、参照のアドレスをNULLにすることができます)。

参照とポインターの違いのリストについては、こちらの回答を参照してください

于 2010-04-14T16:44:07.823 に答える
2

Java(またはC#)で行った方法ではできないことがわかったように。別の提案があります。オブジェクトの参照を引数として渡し、ブール値を返すことができます。結果がコレクションにある場合は、渡される参照に割り当てて「true」を返し、それ以外の場合は「false」を返すことができます。このコードを検討してください。

typedef std::map<string, Operator> OPERATORS_MAP;

bool OperatorList::tryGetOperator(string token, Operator& op)
{
    bool val = false;

    OPERATORS_MAP::iterator it = m_operators.find(token);
    if (it != m_operators.end())
    {
        op = it->second;
        val = true;
    }
    return val;
}

上記の関数は、キー 'token' に対して Operator を見つける必要があります。見つかった場合は true を返し、その値をパラメーター Operator& op に割り当てます。

このルーチンの呼び出し元コードは次のようになります

Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
    //Do something here if true is returned.
}
于 2016-02-20T13:22:49.430 に答える
1

ここでNULLを返すことができない理由は、戻りタイプをとして宣言しているためですAttr&。末尾&は戻り値を「参照」にします。これは基本的に、既存のオブジェクトへのnullにならないことが保証されたポインターです。nullを返すことができるようにする場合は、に変更Attr&Attr*ます。

于 2010-04-14T16:49:18.973 に答える
0

関数の戻り値の型が ではなくNULLオブジェクトであるため、返すことができません。referencepointer

于 2010-04-14T16:45:03.683 に答える
-3

これを試すことができます:

return &Type();
于 2015-12-14T21:08:10.347 に答える