10

重複の可能性:
void ポインターを削除しても安全ですか?

new呼び出されたクラスへの割り当てMyClassがあり、割り当ては次のように簡単だとします。

MyClass *myClassPtr = new MyClass();

void*そして、私が単に言う場所のリストへの参照を保存します

myListOfPointers.add(static_cast<void*>(myClassPtr)); // this has to be void*

そして後で私はメモリを解放するので、代わりに:

delete myClassPtr

私が使う:

delete MyListOfPointer.get(0)

(myClassPtr 参照がゼロ インデックスにあるとします。) また、void*このリストにはさまざまな種類のポインターを格納できるため、削除するポインターの種類がわからないため、そうする必要があることに注意してください。

だから私は次のようなことはできません:

delete static_cast<MyClass*>(MyListOfPointer.get(0))

この方法で正しいメモリサイズを解放できますか? ( sizeof(MyClass))?

注:
スマートポインターを指す答えは探していません。

4

4 に答える 4

14

を介して削除するとvoid*、未定義の動作が発生するため、何も保証されません。

5.3.5 削除 [expr.delete]

1 delete-expression 演算子は、new-expression によって作成された最派生オブジェクト (1.8) または配列を破棄します。
[...]
オペランドには、オブジェクト型へのポインター、またはオブジェクト型へのポインターへの単一の非明示的な変換関数 (12.3.2) を持つクラス型が必要です。結果の型は void です。78

78) これは、void はオブジェクト型ではないため、型 void* のポインターを使用してオブジェクトを削除できないことを意味します。

鉱山を強調します。


言わないでと言いましたが、答えは何らかの形のスマート ポインターを作成することです。type-erasure を使用して外部から型を非表示にする (異種リストを許可する) 必要がありますが、内部的には指定された型とそれを削除する方法を追跡します。によく似たものboost::any

于 2012-10-06T17:15:58.740 に答える
2

voidポインタには型情報がありません。デストラクタがある場合MyClass、呼び出されません。コンパイラは、適切なコードを生成できるように、何を削除しているのかを知る必要があります。リスト内のすべてのポインターが同じタイプの場合、そのタイプを as ではなくリストに格納する必要がありますvoid。ポインターが異なる型であるが、共通の基本型から派生している場合は、その基本型に仮想コンストラクターを与え、代わりにその型のポインターを格納します。

于 2012-10-06T17:31:15.843 に答える
1

スマート ポインターを使用する必要はありません。スマートなだけです。

そうは言っても、他にも多くの可能性があります。唯一のことは、実際のオブジェクトに沿って型情報を格納することです。

class Holder {
public:
    template <typename T>
    explicit Holder(T const volatile* t):
        _data(static_cast<void const volatile*>(t)),
        _delete(&Delete<T>)
    {}

    void apply() { _deleter(_data); }

private:
    typedef void (*Deleter)(void const volatile*);

    template <typename T>
    static void Delete(void const volatile* p) {
        delete static_cast<T const volatile*>(p);
    }

    void const volatile* _data;
    Deleter _deleter;
};

そしていま:

std::list<Holder> owningList;

owningList.push_back(Holder(somePointer));

for (Holder& h: owningList) { h.apply(); }
于 2012-10-06T17:37:47.063 に答える
0

この質問に対する正解はもちろん「いいえ」です

編集:質問へのコメントで既に行ったにもかかわらず、さらに情報を提供するように求められましたが、void* の削除は定義されていません。この質問は、これを尋ねる別の方法です: Is it safe to delete a void pointer? - 詳細については、そこにある回答を参照してください。

于 2012-10-06T17:20:14.350 に答える