- memory_resource[meta header]
- class[meta id-type]
- std::pmr[meta namespace]
- cpp17[meta cpp]
namespace std::pmr {
class memory_resource;
}
memory_resource
はメモリの確保・解放戦略と実際の処理を実装し、polymorphic_allocator
から利用されるためのインターフェースである。
名前 |
説明 |
対応バージョン |
virtual ~memory_resource() |
仮想デストラクタ |
C++17 |
#include <iostream>
#include <memory_resource>
#include <cstddef>
//スタック領域からメモリを割り当てるmemory_resource実装
template<std::size_t N>
struct stack_resource : public std::pmr::memory_resource {
stack_resource() = default;
//コピーに意味がないので禁止
stack_resource(const stack_resource&) = delete;
stack_resource& operator=(const stack_resource&) = delete;
void* do_allocate(std::size_t bytes, std::size_t alignment) override {
//空きがない
if (N <= m_index) throw std::bad_alloc{};
//2の累乗をチェック(AVX512のアライメント要求である64byteを最大としておく)
bool is_pow2 = false;
for (std::size_t pow2 = 1; pow2 <= std::size_t(64); pow2 *= 2) {
if (alignment == pow2) {
is_pow2 = true;
break;
}
}
//2の累乗でないアライメント要求はalignof(std::max_align_t)へ
if (!is_pow2) {
alignment = alignof(std::max_align_t);
}
auto addr = reinterpret_cast<std::uintptr_t>(&m_buffer[m_index]);
//アライメント要求に合わせる
while ((addr & std::uintptr_t(alignment - 1)) != 0) {
++addr;
++m_index;
}
m_index += bytes;
//サイズが足りなくなったら
if (N <= m_index) throw std::bad_alloc{};
return reinterpret_cast<void*>(addr);
}
void do_deallocate(void* p, std::size_t bytes, [[maybe_unused]] std::size_t alignment) override {
auto addr = static_cast<std::byte*>(p);
auto end = std::end(m_buffer);
if (m_buffer <= addr && addr < end) {
//当てた領域をゼロ埋めするだけ
for (std::size_t i = 0; i < bytes; ++i) {
if ((addr + i) < end) {
addr[i] = std::byte(0);
}
}
}
}
bool do_is_equal(const memory_resource& other) const noexcept override {
return this == &other;
}
private:
std::byte m_buffer[N]{};
std::size_t m_index{};
};
int main(){
stack_resource<100> s{};
std::pmr::memory_resource* mr = &s;
//int1つ分の領域をintのアライメント要求(多くの環境で共に4バイト)でメモリ確保
void* p = mr->allocate(sizeof(int), alignof(int));
//placement new して構築
int* p_int = new(p) int{ 256 };
std::cout << *p_int << std::endl;
//一応アドレスを出力
std::cout << p << std::endl;
std::cout << p_int << std::endl;
//デストラクタを呼び出してオブジェクトを破棄
std::destroy_at(p_int);
//メモリの解放
mr->deallocate(p, sizeof(int), alignof(int));
std::cout << std::boolalpha;
stack_resource<10> s2{};
//自分以外とはtrueにならない
std::cout << (*mr == s) << std::endl;
std::cout << (*mr == s2) << std::endl;
}
- std::pmr::memory_resource[color ff0000]
- std::byte[link /reference/cstddef/byte.md]
- allocate[link /reference/memory_resource/memory_resource/allocate.md]
- deallocate[link /reference/memory_resource/memory_resource/deallocate.md]
- std::bad_alloc[link /reference/new/bad_alloc.md]
- std::max_align_t[link /reference/cstddef/max_align_t.md]
- std::uintptr_t[link /reference/cstdint/uintptr_t.md]
- std::destroy_at[link /reference/memory/destroy_at.md]
256
000000308BAFF5D8
000000308BAFF5D8
true
false