1

nullのshared_ptrオブジェクトのメンバー関数にアクセスできます:

#include <memory>
#include <iostream>

class A
{
public:
    int getNum() {return 1234;}
};

int main()
{
    std::shared_ptr<A> pA(nullptr);
    std::cout << pA->getNum() << std::endl;
}

例外を予期していたときに1234を返します。同じ結果が

std::shared_ptr<A> pA();

また

std::shared_ptr<A> pA();
pA.reset();

これは本当に期待される動作ですか?メンバー関数呼び出しの場合に例外をスローするのは、corect shared_ptr定義とは何ですか?

VS2010を使用します。

4

3 に答える 3

9

を呼び出すoperator->()shared_ptrは[util.smartptr.shared.obs]が必要です:

5必要なものget() != 0

これは、get() == 0を呼び出すとoperator->()、未定義の動作が発生することを意味します。未定義の動作は、何かが発生する可能性があることを意味します。例外が発生する可能性があります。あなたはあなたの期待した結果を得ることができました(それが何であれ)。最も近い主要都市のすべてのトイレをバックアップすることができます。何も言えません。

実装がこのコードで何をしているかに関係なく、実装は正しいです。

于 2011-04-05T01:40:21.177 に答える
7

完全な答えはここにあります:

nullインスタンスでメンバー関数を呼び出すと、未定義の動作が発生するのはいつですか?

簡単に言えば、これは未定義の動作であり(または、少なくとも仕様で明確に定義されていない)、タイプを静的に認識し、データを参照しないことを考えると、実際の動作は不合理ではありません。その中で。ただし、この動作を信頼することは、ほぼ確実に良い考えではありません。

于 2011-04-05T01:40:45.780 に答える
6

技術的には、ここで行ったこと未定義の動作を伴います。ただし、getNumメソッドはvirtualまったく使用されておらず、まったく使用thisされていないため、今回はクラッシュしません。理由を理解するために、コンパイラがプログラムを次のように内部的に書き直したと想像してください。

class A { };

int A_getNum(A* this) { return 1234; }

int main()
{
  A* pA = 0;
  std::cout << A_getNum(pA) << '\n';
}

実際のオブジェクトがない場合でも、nullポインターが逆参照Aされることはないため、クラッシュしないことがわかります。これshared_ptrは関係ありません。裸のポインタを使用した場合も同じ効果が得られます。

ヌルポインタで使用されるたびに強制的 にクラッシュさせたい場合は、ええと、標準はないと思います。コンパイラには、オンにできるデバッグオプションがある場合がありますが、たとえば、gcc 4.5を使用してプログラムをコンパイルすると、次のようになります。shared_ptr->-D_GLIBCXX_DEBUG

$ ./a.out 
/usr/include/c++/4.5/bits/shared_ptr_base.h:710: 
_Tp* std::__shared_ptr<_Tp, _Lp>::operator->() const 
[with _Tp = A, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]: 
Assertion '_M_ptr != 0' failed.
Aborted

申し訳ありませんが、MSVCであなたを助けることはできません。

于 2011-04-05T01:46:31.593 に答える