2011-10-24 8 views
5

shared_ptr<void>は、void*deleteを呼び出して、定義されていない動作を呼び出すという点で特別です。なぜshared_ptr <void>は特化していないのですか?

なぜ、コンパイルエラーをスローするshared_ptr<void>特殊化がないのですか?あなたのポインタがmallocのようなものを使用して作成された場合

+0

専門があることが必要となるのはなぜ?それはすでにコンパイルエラーをスローしていませんか? –

+0

@MooingDuck C++委員会で 'delete(void *)0; 'がなぜ許可されたのかは、本当に**不可能**です。それとも、実装者が真剣に取った冗談だったのかもしれません。 – curiousguy

+0

なぜあなたはそれが不可能だと思いますか、@Curiousguy?あたかも委員の全員が死んでいて、メモが残っていないかのようではない。私はほとんどがまだ生きていると確信しており、おそらく議事録と連絡があります。古代の歴史ではありません。それを研究する努力をしてもらいたい人は、それがどうしてそのようになっているのかを正確に伝えることができます。 –

答えて

7

shared_ptr<T>は、T*に変換可能な任意のポインタ型へのポインタを保持でき、UBなしで適切なdeleterを使用するという点で特別です!これは、shared_ptr<Base> p(new Derived);シナリオで動作しますが、shared_ptr<void>も含まれます。例えば

#include <boost/shared_ptr.hpp> 

struct T { 
    T() { std::cout << "T()\n"; } 
    ~T() { std::cout << "~T()\n"; } 
}; 


int main() { 
    boost::shared_ptr<void> sp(new T); 
} 

は出力を生成します。

$ ./test 
T() 
~T() 

あなたがhttp://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/shared_ptr.htmを訪問すれば、立証されている非常にものを見るために割り当てセクションまでスクロールします。詳細は、http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/sp_techniques.html#pvoidを参照してください。

EDIT trinithisによって示されるように、コンストラクタに渡されたポインタの種類がvoid *ポインタである場合、それは、 UBあります。それを指摘してくれてありがとう!

+1

コンストラクタに渡されるポインタ型が 'void *'ポインタの場合、これはUBです。 –

+1

渡されたポインタ型*が* 'void *'であっても、2つの引数を持つコンストラクタを使って、 'delete'を呼び出す以外のことをするカスタムディテクタを渡すことで未定義の動作を避けることはできませんでしたか? –

+0

この回答は、 'boost :: shared_ptr'や' std :: shared_ptr'だけにも当てはまりますか?私は適切な参照を見つけることができません。 –

4

、あなたはdtorfreeを呼び出すshared_ptr<void, dtor>を行うことができます。これにより、定義された動作が発生します。その後、

しかし、再び、おそらくあなたは未定義の動作をしたい:D

1

しかし、それは、多くの状況では、有効です。次のことを考えてみましょう:

class T 
{ 
public: 
    ~T() { std::cout << "~T\n"; } 
}; 

int main() 
{ 
    boost::shared_ptr<void> sp(new T); 
} 

あなたはコンパイルエラーを取得する必要があり、shared_ptrコンストラクタに本物void *を渡すようにしてみてくださいな状況で。

7

Using shared_ptr to hold an arbitrary object

のshared_ptrはvoid *に似た一般的なオブジェクトのポインタとして機能することができます。 shared_ptrのインスタンスを構築する場合:

shared_ptr<void> pv(new X); 

が破壊され、それが正しく〜Xを実行することにより、Xオブジェクトを処分します。

このプロパティは、オブジェクトのポインタから型情報を一時的に取り除くためにraw void *を使用するのとほぼ同じ方法で使用できます。 shared_ptrは後でstatic_pointer_castを使用して正しいタイプにキャストバックできます。

どのようにですか?

This constructor has been changed to a template in order to remember the actual pointer type passed. The destructor will call delete with the same pointer, complete with its original type, even when T does not have a virtual destructor, or is void

関連する問題