3

これを試すと:

#include <functional>
#include <iostream>
#include <memory>
#include <set>

template<class T>
struct MyAlloc
{
    typedef std::allocator<T> Base;
    typedef typename Base::value_type value_type;
    typedef typename Base::pointer pointer;
    typedef typename Base::const_pointer const_pointer;
    typedef typename Base::reference reference;
    typedef typename Base::const_reference const_reference;
    typedef typename Base::size_type size_type;
    typedef typename Base::difference_type difference_type;
    Base a;
    MyAlloc() { }
    template<class U> MyAlloc(MyAlloc<U> const &) { }
    template<class U> struct rebind { typedef MyAlloc<U> other; };
    pointer allocate(size_type n, void const * = NULL)
    {
        std::cout << "Allocating " << n << " objects" << std::endl;
        return this->a.allocate(n);
    }
    void deallocate(pointer p, size_type n) { return this->a.deallocate(p, n); }
};

int main(int argc, char *argv[])
{
    std::set<int, std::less<int>, MyAlloc<int> > set;
}

なるほどAllocating 1 objects

しかし、私には理解できません - なぜこのヒープ割り当てが必要なのですか? スタック メモリは他のコンテナ ( など) をデフォルトで構築するのに十分なのに、std::vectorなぜヒープ割り当てsetを必要とするのでしょうか?map

4

2 に答える 2

0

C++ 標準では、デフォルトで構築されたオブジェクトにメモリを割り当てることを義務付けていません。実装が a のデフォルト コンストラクターで割り当てることを選択する理由std::map<...>はわかりません。理由の 1 つは、スタックに割り当てられたオブジェクトに潜在的に大きなアロケーターを埋め込もうとしないようにすることです。ヒープにメモリを割り当てる理由を確認するには、実装を確認する必要があります。

于 2013-12-29T21:48:10.070 に答える
0

私は自分でそれを理解したと思います。Visual C++ は正しいようで、Clang と GCC は間違っているようです。

orのswapイテレータを無効にしてはならないからです。このコードを試すと:std::setstd::map

#include <set>
#include <iostream>
int main()
{
    std::set<int> a, b;
    std::set<int>::iterator end = a.end();
    a.swap(b);
    b.insert(end, 1);
    std::cout << b.size() << std::endl;
    return 0;
}

ツリーの先頭がスタックに格納されていた場合end、スワップ後に無効になります。

Visual C++ は問題なく処理しますが、GCC と Clang は無限にループします (少なくとも私のバージョンでは)。

編集:上記はあいまいさのためにC++03までの理由であった可能性がありますが、C++11以降はそうではありません-以下のコメントを参照してください。

于 2013-12-29T22:24:18.567 に答える