コンテナクラスのメモリはスタックorヒープ?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
モナモナ

コンテナクラスのメモリはスタックorヒープ?

#1

投稿記事 by モナモナ » 7年前

初めまして。コンテナクラスのメモリの仕様についての質問です。
arrayやvector等のコンテナクラスで使用するメモリは、ヒープ領域に確保されるのでしょうか?
よろしくお願いします。

かずま

Re: コンテナクラスのメモリはスタックorヒープ?

#2

投稿記事 by かずま » 7年前

class array は組み込み配列のラッパーとして実装されるので、
ヒープではなくスタックですね。

コード:

#include <iostream>
#include <array>

using namespace std;

int main()
{
    array<int, 5> a;
    for (int i = 0; i < 5; i++) a[i] = i;

    struct { int _[5]; } b;
    for (int i = 0; i < 5; i++) b._[i] = i;
}
a と b._ がほぼ同じ。

モナモナ

Re: コンテナクラスのメモリはスタックorヒープ?

#3

投稿記事 by モナモナ » 7年前

vectorの場合はヒープ領域で確保されるのでしょうか?
おそらく内部でmallocやreallocを使っていますよね?

かずま

Re: コンテナクラスのメモリはスタックorヒープ?

#4

投稿記事 by かずま » 7年前

vector はテンプレートの第2引数のデフォルトが allocatorクラスなので、
おそらく new と delete でヒープに領域を確保しているでしょう。

でも、allocator を自分で実装すれば、スタックにすることもできるでしょう。

コード:

#include <iostream>
#include <vector>
using namespace std;

int *ptr;

struct FakeAllocator {
    typedef int value_type;
    template <class U> struct rebind { typedef FakeAllocator other; };
    int* allocate(size_t n) { return ptr; }
    void deallocate(int* p, size_t n) { }
};

int main()
{
    int buf[1024];
    ptr = buf;

    vector<int, FakeAllocator> a(5);

    cout << "  buf = " << buf << endl;
    cout << "&a[0] = " << &a[0] << endl;
    for (int i = 0; i < 5; i++) a[i] = i + 1;
    for (int i = 0; i < 5; i++) cout << ' ' << a[i];
    cout << endl;
}

モナモナ

Re: コンテナクラスのメモリはスタックorヒープ?

#5

投稿記事 by モナモナ » 7年前

気になっていたことが、解決しました。ありがとうございました。

かずま

Re: コンテナクラスのメモリはスタックorヒープ?

#6

投稿記事 by かずま » 7年前

FakeAllocator がフェイク過ぎて、毎回同じアドレスを
返すなんて使い物にならないだろうと気になっていたので、
もうちょっとましな実装に変えてみました。

コード:

#include <iostream>
#include <vector>
using namespace std;
 
struct FakeAllocator {
    typedef int value_type;
    template <class U> struct rebind { typedef FakeAllocator other; };
    int* allocate(size_t n) {
        ptr += n;
        cout << "allocate: ptr = " << ptr << endl;
        return ptr - n;
    }
    void deallocate(int* p, size_t n) {
        if (p + n == ptr) ptr -= n;
        cout << "deallocate: ptr = " << ptr << endl;
    }
    static void set(int *p) {
        ptr = p;
        cout << "set: ptr = " << ptr << endl;
    }
    static int* ptr;
};

int* FakeAllocator::ptr;
 
int main()
{
    int buf[1024];
    FakeAllocator::set(buf);
 
    vector<int, FakeAllocator> a(3);
    vector<int, FakeAllocator> b(5);
    vector<int, FakeAllocator> c(4);
 
    cout << "  buf = " << buf << endl;
    cout << "&a[0] = " << &a[0] << endl;
    cout << "&b[0] = " << &b[0] << endl;
    cout << "&c[0] = " << &c[0] << endl;
}
g++ による実行結果

コード:

set: ptr = 0xffffbbc0
allocate: ptr = 0xffffbbcc
allocate: ptr = 0xffffbbe0
allocate: ptr = 0xffffbbf0
  buf = 0xffffbbc0
&a[0] = 0xffffbbc0
&b[0] = 0xffffbbcc
&c[0] = 0xffffbbe0
deallocate: ptr = 0xffffbbe0
deallocate: ptr = 0xffffbbcc
deallocate: ptr = 0xffffbbc0
用意された領域を使い切ったかどうかのチェックをしていないので
まだ不完全ですが、とにかく、デフォルトの allocator より
高速な処理になることは確かです。

返信

“C言語何でも質問掲示板” へ戻る