51

スマートポインターのことを聞いたことがなかった古いコードプロジェクトのいくつかでは、ポインターがまだ有効なオブジェクトを指しているかどうかを確認する必要があるときはいつでも、常に次のようなことをしていました...

object * meh = new object;
if(meh) 
    meh->member;

または、オブジェクトを安全に削除する必要がある場合は、次のようになります

if(meh)
{
    delete meh;
    meh = 0;
}

さて、今、私はブール式でオブジェクトとポインタを両方ともリテラル数で使用することから発生する可能性のある問題について学びました。難しい方法です:。そして今、私は、nullptrキーワードであるC++のそれほど新しくはないがかなりクールな機能についても学びました。しかし今、私は興味があります。

私はすでにほとんどのコードを調べて修正しているので、たとえば、オブジェクトを削除するときに今書いている

if(meh)
{
    delete meh;
    meh = nullptr;
}

今、私はブール値について疑問に思っています。あなたが渡すとき、このようなifステートメントにintを言うだけです、

int meh;
if(meh)

次に、それを書き込む必要なしに、暗黙的にゼロをチェックします。

if(meh == 0) // does the exact same check

さて、C ++はポインターに対して同じことをしますか?このようなchar*をifステートメントに渡す場合はどうなりますか?

char * meh;
if(meh)

それでは、暗黙的にnullptrと比較しますか?私はこのようなifを長い間書いてきたので、if(object *)と入力してそのメンバーを呼び出すことにより、使用する前にポインターが有効かどうかを確認するのがこの時点での第2の性質です。これが機能ではない場合はどうしてですか?実装が難しすぎる?コードを台無しにする可能性のあるさらに別の小さな方法を削除することで、いくつかの問題を解決します。

4

2 に答える 2

55

Cでは、0以外のものはすべて真です。だから、あなたは確かに使うことができます:

if (ptrToObject) 
    ptrToObject->doSomething();

ポインタを安全に逆参照します。

C ++ 11はゲームを少し変更し、nullptr_tそのタイプはnullptrインスタンスです。の表現nullptr_tは実装固有です。したがって、コンパイラはnullptr_t必要に応じて定義できます。nullptr_tさまざまなタイプ(ブール値が許可されている)へのキャストに適切な制限を適用できることを確認し、anullptr_tと0を区別できることを確認するだけで済みます。

したがって、コンパイラがC ++ 11言語仕様に準拠している限り、ブール値nullptrに適切かつ暗黙的にキャストされます。そして、上記のスニペットは引き続き機能します。 false

参照されたオブジェクトを削除しても、何も変更されません。

delete ptrToObject;
assert(ptrToObject);
ptrToObject = nullptr;
assert(!ptrToObject);    

私はこのようなifを長い間書いてきたので、if(object *)と入力してそのメンバーを呼び出すことにより、使用する前にポインターが有効かどうかを確認するのがこの時点での第2の性質です。

いいえ。オブジェクトの適切なグラフを維持してください(できれば、一意の/スマートポインターを使用してください)。指摘したようnullptrに、有効なオブジェクトを指していないポインタが有効かどうかを判断する方法はありません。とにかくライフサイクルを維持する責任はあなたにあります。これが、ポインタラッパーがそもそも存在する理由です。

実際、共有ポインターとポインタ​​ーのライフサイクルは明確に定義されているため、有効なポインターには値があり、他のすべてのポインターは次のようになりますnullptr

共有

#include <iostream>
#include <memory>

void report(std::shared_ptr<int> ptr) 
{
    if (ptr) {
        std::cout << "*ptr=" << *ptr << "\n";
    } else {
        std::cout << "ptr is not a valid pointer.\n";
    }
}

int main()
{
    std::shared_ptr<int> ptr;
    report(ptr);

    ptr = std::make_shared<int>(7);
    report(ptr);
}

弱い

#include <iostream>
#include <memory>

void observe(std::weak_ptr<int> weak) 
{
    if (auto observe = weak.lock()) {
        std::cout << "\tobserve() able to lock weak_ptr<>, value=" << *observe << "\n";
    } else {
        std::cout << "\tobserve() unable to lock weak_ptr<>\n";
    }
}

int main()
{
    std::weak_ptr<int> weak;
    std::cout << "weak_ptr<> not yet initialized\n";
    observe(weak);

    {
        auto shared = std::make_shared<int>(42);
        weak = shared;
        std::cout << "weak_ptr<> initialized with shared_ptr.\n";
        observe(weak);
    }

    std::cout << "shared_ptr<> has been destructed due to scope exit.\n";
    observe(weak);
}

さて、C ++はポインターに対して同じことをしますか?このようなchar*をifステートメントに渡す場合はどうなりますか?

だから質問に答えるために:裸のポインタで、いいえラップされたポインタを使用すると、はい

皆さん、ポインタをラップしてください。

于 2012-07-01T05:08:35.437 に答える
14

ポインタが有効なオブジェクトを指しているかどうかをテストすることはできません。ポインタがnullではないが、有効なオブジェクトを指していない場合、ポインタを使用すると未定義の動作が発生します。この種のエラーを回避するために、ポイントされているオブジェクトの存続期間に注意する責任があります。スマートポインタクラスはこのタスクに役立ちます。

が生のポインタである場合、ととの間にmehは何の違いもありませif (meh)ん。ポインタがnullでない場合、これらはすべて続行します。if (meh != 0)if (meh != nullptr)

0リテラルから。への暗黙の変換がありnullptrます。

于 2014-09-08T00:25:08.527 に答える