visual studio 2012(以降vs2012)で、空のshared_ptrを生成するとuser_countで得られる値が、cpprefjpで確認した挙動と違ったので、確認してみるとvs2012だけ挙動が違ってたっぽい。
挙動を確認したコード
#include <iostream>
#include <memory>
template <class T, class P>
void print( T&& str, P&& p ) {
std::cout << str << ":" << p.use_count() << " ";
if ( p ) {
std::cout << "exist" << std::endl;
} else {
std::cout << "null" << std::endl;
}
}
int main()
{
std::shared_ptr<int> p1;
print( "p1", p1 );
std::shared_ptr<int> p2( nullptr );
print( "p2", p2 );
std::shared_ptr<int> p3( nullptr, std::default_delete<int>() );
print( "p3", p3 );
std::shared_ptr<int> p4( nullptr, std::default_delete<int>(), std::allocator<void>() );
print( "p4", p4 );
std::shared_ptr<int> p5 = nullptr;
print( "p5", p5 );
std::shared_ptr<int> p6( new int );
p6 = nullptr;
print( "p6", p6 );
return 0;
}
これを実行すると、cpprefjpの通りなら、デリータやアロケータを渡しているp3,p4だけ、use_countが1になるはず。
Wandboxで、gccとclangを使ってコンパイルすると、ちゃんとリファレンス通りの結果になる。
・gcc 4.7.3
・clang 3.2
※コンパイラのバージョンはC++11に対応したできるだけ古いバージョンで比較
vs2015以降は、gccやclangと同じ結果になった。vs2013は知らない。
vs2012で空のshared_ptrを作りたい場合は、デフォルトコンストラクタを使おうってことだけど、もうvs2012自体使うことないか。
おまけ
shared_ptr クラス - MSDN - Microsoft visual studio 2015には、
null ポインターを使用して初期化される shared_ptr オブジェクトにはコントロール ブロックが存在し、空ではありません。
空の shared_ptr オブジェクトは、リソースを一切所有せず、コントロール ブロックも持ちません。
引数なし: 結果として生成されるオブジェクトは、空の shared_ptr オブジェクトまたは空の weak_ptr オブジェクトです。
デフォルトコンストラクタから生成されるのは、コントロールブロックもない空shared_ptrオブジェクトで、nullptrを渡した場合は、コントロールブロックが作られるので空オブジェクトじゃないと言ってるが、実装はこうなっていた。
constexpr shared_ptr() _NOEXCEPT
{ // construct empty shared_ptr
}
constexpr shared_ptr(nullptr_t) _NOEXCEPT
{ // construct empty shared_ptr
}
どう見ても両方共空shared_ptrオブジェクト生成しそうだが。
vs2012も同じ文章だったので、vs2012の実装に合わせて書いてそのままということなのだろうか。