2017-12-16 4 views
2

を削除するカスタム呼び出す方法をカスタム削除[]演算子:私が持っているオペレータ

void operator delete[](void *ptr, char const* file, int line) noexcept {...} 

私はそれを呼び出すようにしようと、それは単純ではなく、私のカスタム演算子を[](ボイド* ptrに)を削除呼び出します。

char *b = new char[256]; 
delete[] b, __FILE__, __LINE__; 

これはコンパイルされますが、カスタムオペレータ権限への呼び出しですか?

答えて

3

delete式を使用すると、デフォルトのoperator delete(void*)が呼び出されます。配列の使用に似ています。唯一のケースでは、operator delete()が呼び出されるのは、operator new()が呼び出された後にオブジェクトのコンストラクタによって例外がスローされた場合です。

カスタムoperator new()を使用している場合、すなわち、new(a, b) T(...)のようないくつかの配置構文を使用して、手動でオブジェクトを破壊し、対応するメモリを解放する必要があります:

T* ptr = new(__FILE__, __LINE__) T(args); 
// ... 
ptr->~T(); // destroy the object 
operator delete(ptr, __FILE__, __LINE__); 

「ノーマル」を交換したり、過負荷にoperator new()/operator delete()、すなわち、署名

void* operator new(std::size_t) 
void operator delete(void*) 

(及び対応する配列型)、いずれかのグローバルバージョンを置き換えるまたはクラス固有のオーバーロードを使用することによって、すなわち、correspo staticのメンバーでは、デストラクタとoperator delete()deleteという式で呼び出されます。

+1

"手動でオブジェクトを破棄し、対応するメモリを解放する必要があります"クラス内で普通の 'operator delete()'(解放関数)を実装し、 'operator delete'というプレースメントから呼び出します。次に、 'delete'式がデストラクタを呼び出すようにします。 –

+0

@ Cheersandhth.-Alf:これは、置き換えられたバージョンにのみ当てはまり、過負荷には当てはまりません( 'std :: nothrow'変形を除く)。引数を 'new'式に渡すと、私の答えに記述されているようにオブジェクトを手動で解放する必要があります。 –

+0

"代替バージョン"とは、クラス内のオーバーロードを意味し、グローバルオーバーヘッドの機能を意味する "オーバーロード"を意味するという点があります。申し訳ありませんが、私はそれを考えませんでした。それでも、クラス固有の割り当て関数には同じ 'new'式構文が使用されます。そして、「あなたが使うならば...」というパラは、暗黙の普遍的な定量化で間違っています。 –

0

https://en.wikipedia.org/w/index.php?title=Placement_syntax&action=edit&section=9によれば、配置削除構文はありません。演算子newと一致するように 'placement'演算子の削除オーバーロードが必要ですが、新しい配置演算子を使用して呼び出すことはできません。

演算子のdelete overloadは、作成中のオブジェクトのctorで例外が発生した場合などに呼び出されます。

1

声明

delete[] b, __FILE__, __LINE__; 

は...コンマ式ではなく、配置delete関数の呼び出しです。

delete式でプレースメントを呼び出すための構文はありませんdelete関数(割り当て解除関数)。この目的を仮定

ブロックを削除するソースコードの位置を記録または検査することであり、割り当てられた、次のようなことを行うことができます。

#include <stddef.h>  // size_t 
#include <type_traits> // std::aligned_storage 
#include <iostream> 
#include <memory>  // std::unique_ptr 
#include <new>   // ::new() 

namespace my{ 
    using std::clog; 
    using std::aligned_storage; 

    using Byte = unsigned char; 

    struct Sourcecode_location 
    { 
     char const*  file; 
     int    line; 
    }; 

    constexpr size_t info_size = sizeof(Sourcecode_location); 
    constexpr size_t info_align = alignof(Sourcecode_location); 

    auto location_info_ptr(void* const p_array, size_t const size) 
     -> Sourcecode_location* 
    { 
     const size_t n = ((info_align - 1) + size)/info_align; 
     return reinterpret_cast<Sourcecode_location*>(
      reinterpret_cast<Byte*>(p_array) + n*info_align 
      ); 
    } 

    class Foo 
    { 
     using This_class = Foo; 

     static void report_delete_of(void* ptr, Sourcecode_location const& loc) 
     { 
      clog << "Foo[] " << ptr << " deleted, was allocated at " << loc.file << "(" << loc.line << ")\n"; 
     } 

     static void deallocate_array(void* p) { ::operator delete[](p); } 

    public: 
     auto operator new[](size_t const size) 
      -> void* 
     { return This_class::operator new[](size, "<unknown>", 0); } 

     // If this function is defined it's called instead of the one after here: 
     // void operator delete[](void* const ptr) 

     void operator delete[](void* const ptr, size_t const size) 
      noexcept 
     { 
      clog << "(The size of the following was " << size << " bytes.)\n"; 
      report_delete_of(ptr, *location_info_ptr(ptr, size)); 
      deallocate_array(ptr); 
     } 

     auto operator new[](size_t const size, char const* const file, int const line) 
      -> void* 
     { 
      const size_t n = ((info_align - 1) + size)/info_align; // To cover array. 
      void* const p = ::operator new[](n*info_align + info_size); 
      ::new(location_info_ptr(p, size)) Sourcecode_location{ file, line }; 
      clog << "new Foo[] " << p << " of size " << size << " at " << file << "(" << line << ")\n"; 
      return p; 
     } 

     // Called by construction failure in a placement new expression: 
     void operator delete[](void* const ptr, char const* const file, int const line) 
      noexcept 
     { 
      clog << "(The following array's size was not given)\n"; 
      report_delete_of(ptr, {file, line}); 
      deallocate_array(ptr); 
     } 

    public: 
     ~Foo() {} // Without this MSVC 29017 provides wrong size to deallocation function. 

     Foo() {} 
    }; 
} // namespace my 

auto main() 
    -> int 
{ 
    using namespace std; 

    auto p = unique_ptr<my::Foo[]>{ new(__FILE__, __LINE__) my::Foo[3] }; 
    clog << "\n"; 
} 

典型的出力:

 
new Foo[] 0x3aa08 of size 7 at a.cpp(89) 

(The size of the following was 7 bytes.) 
Foo[] 0x3aa08 deleted, was allocated at a.cpp(89)