声明
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)
"手動でオブジェクトを破棄し、対応するメモリを解放する必要があります"クラス内で普通の 'operator delete()'(解放関数)を実装し、 'operator delete'というプレースメントから呼び出します。次に、 'delete'式がデストラクタを呼び出すようにします。 –
@ Cheersandhth.-Alf:これは、置き換えられたバージョンにのみ当てはまり、過負荷には当てはまりません( 'std :: nothrow'変形を除く)。引数を 'new'式に渡すと、私の答えに記述されているようにオブジェクトを手動で解放する必要があります。 –
"代替バージョン"とは、クラス内のオーバーロードを意味し、グローバルオーバーヘッドの機能を意味する "オーバーロード"を意味するという点があります。申し訳ありませんが、私はそれを考えませんでした。それでも、クラス固有の割り当て関数には同じ 'new'式構文が使用されます。そして、「あなたが使うならば...」というパラは、暗黙の普遍的な定量化で間違っています。 –