2

重複の可能性:
パブリック演算子new、プライベート演算子delete:newを使用するとC2248が「プライベートメンバーにアクセスできません」になります

http://efesx.com/2009/12/01/public-operator-new-and-private-operator-delete/

この記事では、このコードでエラーが発生するはずだと読みました。

#include <cstdlib>

struct Try {
        Try () { /* o/ */ }

        void *operator new (size_t size) {
            return malloc(size);
        }

    private:
        void operator delete (void *obj) {
            free(obj);
        }
};

int main () {
    Try *t = new Try();

    return 0;
}

私はgcc4.7.1でそれを試しました:

Compilation finished with errors: source.cpp: In function 'int
main()': source.cpp:11:14: error: 'static void Try::operator
delete(void*)' is private source.cpp:17:22: error: within this context
source.cpp:11:14: error: 'static void Try::operator delete(void*)' is
private source.cpp:17:22: error: within this context source.cpp:17:10:
warning: unused variable 't' [-Wunused-variable]

この記事のコメントで、私はこのリンクを見ました-パブリックオペレーター新規、プライベートオペレーター削除:新規使用時にC2248を「プライベートメンバーにアクセスできません」

私がそれを正しく理解していない場合、コンパイラは適切な演算子deleteを呼び出すことによってコンストラクタから例外がスローされた状況でメモリリークを回避する必要があるため、コンパイルされません。しかし、なぜこのコードはコンパイルされて機能するのでしょうか?

#include <cstdlib>

struct Try {
        void *operator new (size_t size) {
            return malloc(size);
        }

    private:
        void operator delete (void *obj) {
            free(obj);
        }
};

int main () {
    Try *t = new Try;

    return 0;
}

標準で正しいですか?

そして、このコードはどうですか?

#include <cstdlib>

struct Try {
        void *operator new (size_t size) {
            return malloc(size);
        }

    private:
        void operator delete (void *obj) {
            free(obj);
        }
};

int main () {
    Try *t = new Try();

    return 0;
}

gcc4.7.1ではコンパイルされません。

そして、このようなものを標準ライブラリにどのように実装する必要がありますか?

Comeauは、これらすべての例をコンパイルしているわけではありません。

"ComeauTest.c", line 15: error: function "Try::operator delete"
(declared at line 9) is inaccessible Try *t = new Try; ^

誰かが私にこれを詳しく説明してもらえますか?

4

2 に答える 2

2
  • 最初の例については正しいようです。

2 番目と 3 番目の例では、POD タイプを扱います。そして、初期化の違いが役割を果たします。

  • 2 番目の例では、構造が初期化されていません。問題ありません。

  • 反対に、3 番目の例では構造初期化されるため、最初のケースになります。

編集:

次に、operator newそれ自体が例外をスローできます。標準 (c++11 darft によると):

式が例外をスローして終了する場合new、解放関数 (3.7.4.2) を呼び出してストレージを解放できます。割り当てられた型が非配列型の場合、割り当て関数の名前は operator newであり、割り当て解除関数の名前はoperator deleteです。

ストレージを解放する可能性があると言って、作成者が何を表現したかったのかは少し不明です。リリースされた場合、実装定義のようです。

newとにかく、投げないバージョンを試すことができます:

void *operator new (size_t size, std::nothrow_t) throw() {
    return malloc(size);
}
于 2012-09-21T18:49:49.020 に答える
0

コンストラクターコードが例外をスローした場合に備えて、newおよびdeleteの演算子を含むコンストラクターコードを作成するコンパイラー。したがって、newを使用すると、 deleteの使用法が自動的に作成されます。

2番目の例では、コンパイラーは、スローしないデフォルトのコンストラクターを使用していることを認識しています(私の推測)。

コンパイラが異なれば、動作も異なります(キャプテン)。また、コードを作成するための最適化機能とトリックも異なります。

于 2012-09-21T19:55:25.407 に答える