какая-то чертовщина с std::map
От: yatagarasu Беларусь  
Дата: 27.11.09 12:07
Оценка:
Всем привет. Давно тут не писал, так что немного стесняюсь...

Придумал я велосипед такой, хочу знать ващего мнения.
Есть класс, который наследуется от std::pair<key, указатель на самого себя>
ожидал я от него, что он будет сам себя в мапе хранить. О мапе своем все знать, и ключь свой при себе держать.
А лучше кодом напишу.

    class Paired : public std::pair<int, Paired *>
    {
        std::map<int, Paired *> &owner_;
        int &name_;

    public:
        Paired(int i, std::map<int, Paired *> &o)
            : std::pair<int, Paired *>(i, this)
            , owner_(o)
            , name_(first)
        {
        }

        std::string Name() const
        {
            if (name_ == 1) return "one";
            if (name_ == 2) return "two";
            if (name_ == 3) return "three";

            return "none";
        }

        void Move()
        {
            owner_.erase(first);
            name_ += 512;
            owner_.insert(*this);
        }
    };

    void test()
    {
        typedef std::map<int, Paired *> m_t;
//            Paired<std::pair<int, void *> > p;
        m_t m;

        // 11111111111111
        m.insert(Paired(1, m));
        m.insert(Paired(2, m));
        m.insert(Paired(3, m));
        m.insert(Paired(4, m));
        m.insert(Paired(5, m));
        m.insert(Paired(6, m));
        m.insert(Paired(7, m));
        m.insert(Paired(8, m));
        m.insert(Paired(9, m));
        m.insert(Paired(10, m));
        m.insert(Paired(11, m));
        m.insert(Paired(12, m));

        for (m_t::iterator i = m.begin(); i != m.end(); i++)
        {
            printf("%d %s\n", (*i).first, (*i).second->Name().c_str());
        }


        /// 222222222222222222
        m_t::iterator mi = m.begin()
                   , mie = --m.end();
        while (mi != mie)
        {
            m_t::iterator p = mi++;
            (*p).second->Move();
        }
        (*mie).second->Move();

        for (m_t::iterator i = m.begin(); i != m.end(); i++)
        {
            printf("%d %s\n", (*i).first, (*i).second->Name().c_str());
        }
    }


И самое удивительное что оно работает.
Эт только потом я вспомнил про слайсинг. Подумал о том что надо бы в мапе похорошему std::pair на мой класс заменить. но это не возможно.
Хотя с другой стороный если объекты будут хранится в другом каком-нить контейнере, а потом в мап попадать, не пофиг ли на слайсинг?
Ну и место 2, ваще уродство имхо. но ниче не поделаешь.

И что это за вилосипед я изобрел? И поедет ли он в дальний путь?
std::map std::pair велосипед
Re: какая-то чертовщина с std::map
От: sokel Россия  
Дата: 27.11.09 14:29
Оценка: 3 (1)
Здравствуйте, yatagarasu, Вы писали:

Y>Всем привет. Давно тут не писал, так что немного стесняюсь...


Y>Придумал я велосипед такой, хочу знать ващего мнения.

Y>Есть класс, который наследуется от std::pair<key, указатель на самого себя>
Y>ожидал я от него, что он будет сам себя в мапе хранить. О мапе своем все знать, и ключь свой при себе держать.

Посмотри на интрузивные контейнеры (boost::intrusive). Там ты как раз сможешь ноду для контейнера самодельную сделать.
плюсы:
— ключ дублироваться не будет
— объект к итератору кастуется
— содержащий контейнер можно получить по цепочке: to_iterator(obj) -> to_end_iterator(iterator) -> container_from_end(end_iterator)

Только вот аллокатор будет внешним.
Re: какая-то чертовщина с std::map
От: sokel Россия  
Дата: 27.11.09 14:57
Оценка: +1
Здравствуйте, yatagarasu, Вы писали:

Y>Придумал я велосипед такой, хочу знать ващего мнения.

Y>Есть класс, который наследуется от std::pair<key, указатель на самого себя>
Y>ожидал я от него, что он будет сам себя в мапе хранить. О мапе своем все знать, и ключь свой при себе держать.
Y>И самое удивительное что оно работает.

Оно работает небось только под debug и то по счастливой случайности. Потому как при вставке происходит срезка объекта Paired до базового класса. Указатель при этом ссылается на созданный на стеке временный объект типа Paired. Так что это чистое везение что этот самый Paired не был переписан.
Re: какая-то чертовщина с std::map
От: Centaur Россия  
Дата: 27.11.09 15:24
Оценка:
Здравствуйте, yatagarasu, Вы писали:

Y>Придумал я велосипед такой, хочу знать ващего мнения.

Y>Есть класс, который наследуется от std::pair<key, указатель на самого себя>
Y>ожидал я от него, что он будет сам себя в мапе хранить. О мапе своем все знать, и ключь свой при себе держать.

Изначально нерабочий подход. А если кто-то скажет тому map’у erase, а объекту об этом не скажет? А особенно в другой map пересадит?

Y>        int &name_;

Не нужен. Раз мы наследуемся от std::pair, то first нам и так будет виден.

Y>    void test()
Y>    {
Y>        typedef std::map<int, Paired *> m_t;
Y>//            Paired<std::pair<int, void *> > p;
Y>        m_t m;

Y>        // 11111111111111
Y>        m.insert(Paired(1, m));
Y>        m.insert(Paired(2, m));
Y>        m.insert(Paired(3, m));
Y>        m.insert(Paired(4, m));
Y>        m.insert(Paired(5, m));
Y>        m.insert(Paired(6, m));
Y>        m.insert(Paired(7, m));
Y>        m.insert(Paired(8, m));
Y>        m.insert(Paired(9, m));
Y>        m.insert(Paired(10, m));
Y>        m.insert(Paired(11, m));
Y>        m.insert(Paired(12, m));

Создали временный объект, он запомнил указатель на себя; срезали его в std::pair в map’е, указатель скопировался; убили временный объект — указатель в pair остался указывать на труп. Итого, к этому моменту у нас есть map, содержащий 12 указателей на трупы.

Y>        for (m_t::iterator i = m.begin(); i != m.end(); i++)
Y>        {
Y>            printf("%d %s\n", (*i).first, (*i).second->Name().c_str());
Y>        }

А вот теперь начинается некромантия. «Взвод трупов, по порядку номеров — рассчитайсь!»
OK, если нам повезло, временные объекты создавались по разным адресам, а трупы ещё не успели разложиться. Первый. Второй. Третий. […] Двенадцатый, расчёт закончен.

Y>        /// 222222222222222222
Y>        m_t::iterator mi = m.begin()
Y>                   , mie = --m.end();
Y>        while (mi != mie)
Y>        {
Y>            m_t::iterator p = mi++;
Y>            (*p).second->Move();
Y>        }
Y>        (*mie).second->Move();

О ужас. Я это даже представить себе не могу, буду рисовать.
// исходное положение
  1   2   3   4   5   6   7   8   9  10  11  12
 x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
^  |
|  |             .------.
|  v             v      |
|  .-x_X----------------|------------.
|  |        |       |   *    |       |
|  | owner_ | first | second | name_ |
'----*      |   1   |        |   *   |
   '--------------------^--------|---'
                        |        |
                        '--------'
// остальных зомби разрисовывать не буду
// порядок полей не соответствует реальному

------------------------------------------------
// сразу после входа в тело цикла
  1   2   3   4   5   6   7   8   9  10  11  12
 x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x

^mi                                         ^mie
------------------------------------------------
// m_t::iterator p = mi++;
  1   2   3   4   5   6   7   8   9  10  11  12
 x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x

^p  ^mi                                     ^mie
------------------------------------------------
// (*p).second->Move();
//            owner_.erase(first);
.---> 2   3   4   5   6   7   8   9  10  11  12
|    x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
|
|   ^mi                                     ^mie
|
|                .------.
|                v      |
|  .-x_X----------------|------------.
|  |        |       |   *    |       |
|  | owner_ | first | second | name_ |
'----*      |   1   |        |   *   |
   '--------------------^--------|---'
                        |        |
                        '--------'

------------------------------------------------
//            name_ += 512;
.---> 2   3   4   5   6   7   8   9  10  11  12
|    x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
|
|   ^mi                                     ^mie
|
|                .------.
|                v      |
|  .-x_X----------------|------------.
|  |        |       |   *    |       |
|  | owner_ | first | second | name_ |
'----*      |  513  |        |   *   |
   '--------------------^--------|---'
                        |        |
                        '--------'

------------------------------------------------
//            owner_.insert(*this);
.---> 2   3   4   5   6   7   8   9  10  11  12  513
|    x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
|                                                 |
|   ^mi                                     ^mie  |
|                                                 |
|                .--------------------------------'
|                v      |
|  .-x_X----------------|------------.
|  |        |       |   *    |       |
|  | owner_ | first | second | name_ |
'----*      |  513  |        |   *   |
   '--------------------^--------|---'
                        |        |
                        '--------'
------------------------------------------------

Это всё, конечно, в предположении, что трупы каким-то неведомым образом продолжают не тухнуть. Потому что, будь я компилятор, я бы уже второго Paired положил на место уже мёртвого первого. И все временные переменные в методах erase и insert имеют полное право занять их место.

Y>И что это за вилосипед я изобрел? И поедет ли он в дальний путь?


Как только на кладбище построят что-нибудь полезное, а потом попытаются в очередной раз взводом зомби покомандовать, всё и упадёт.
Re[2]: какая-то чертовщина с std::map
От: yatagarasu Беларусь  
Дата: 27.11.09 16:40
Оценка:
Здравствуйте, sokel, Вы писали:

S>Здравствуйте, yatagarasu, Вы писали:


Y>>Всем привет. Давно тут не писал, так что немного стесняюсь...


Y>>Придумал я велосипед такой, хочу знать ващего мнения.

Y>>Есть класс, который наследуется от std::pair<key, указатель на самого себя>
Y>>ожидал я от него, что он будет сам себя в мапе хранить. О мапе своем все знать, и ключь свой при себе держать.

S>Посмотри на интрузивные контейнеры (boost::intrusive). Там ты как раз сможешь ноду для контейнера самодельную сделать.

S>плюсы:
S>- ключ дублироваться не будет
S>- объект к итератору кастуется
S>- содержащий контейнер можно получить по цепочке: to_iterator(obj) -> to_end_iterator(iterator) -> container_from_end(end_iterator)

S>Только вот аллокатор будет внешним.


о, похоже это то велосипед что я искал. спс.
Re[2]: какая-то чертовщина с std::map
От: yatagarasu Беларусь  
Дата: 27.11.09 16:57
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Здравствуйте, yatagarasu, Вы писали:


Y>>Придумал я велосипед такой, хочу знать ващего мнения.

Y>>Есть класс, который наследуется от std::pair<key, указатель на самого себя>
Y>>ожидал я от него, что он будет сам себя в мапе хранить. О мапе своем все знать, и ключь свой при себе держать.

C>Изначально нерабочий подход. А если кто-то скажет тому map’у erase, а объекту об этом не скажет? А особенно в другой map пересадит?

тот сам себе будет злым буратиной. вообще этот велосипед такого неподразумевает. он еще недописан и там щиты чтобы стружка не вылетала и наклейки "отрубит пальцы если сунешь".

C>
Y>>        int &name_;
C>

C>Не нужен. Раз мы наследуемся от std::pair, то first нам и так будет виден.
идея не в том чтобы наследоваться от паир, а в том чтобы использовать переменную класса как ключ.
как вариант мне потом посоветовали использовать std::set со своей функцией сравнения.

C>
Y>>    void test()
Y>>    {
Y>>        typedef std::map<int, Paired *> m_t;
Y>>//            Paired<std::pair<int, void *> > p;
Y>>        m_t m;

Y>>        // 11111111111111
Y>>        m.insert(Paired(1, m));
Y>>        m.insert(Paired(2, m));
Y>>        m.insert(Paired(3, m));
Y>>        m.insert(Paired(4, m));
Y>>        m.insert(Paired(5, m));
Y>>        m.insert(Paired(6, m));
Y>>        m.insert(Paired(7, m));
Y>>        m.insert(Paired(8, m));
Y>>        m.insert(Paired(9, m));
Y>>        m.insert(Paired(10, m));
Y>>        m.insert(Paired(11, m));
Y>>        m.insert(Paired(12, m));
C>

C>Создали временный объект, он запомнил указатель на себя; срезали его в std::pair в map’е, указатель скопировался; убили временный объект — указатель в pair остался указывать на труп. Итого, к этому моменту у нас есть map, содержащий 12 указателей на трупы.
ох стар стал. не помню уже. не уверен доживут ли они до закрывающей скобки }. но это прототип.

C>
Y>>        for (m_t::iterator i = m.begin(); i != m.end(); i++)
Y>>        {
Y>>            printf("%d %s\n", (*i).first, (*i).second->Name().c_str());
Y>>        }
C>

C>А вот теперь начинается некромантия. «Взвод трупов, по порядку номеров — рассчитайсь!»
C>OK, если нам повезло, временные объекты создавались по разным адресам, а трупы ещё не успели разложиться. Первый. Второй. Третий. […] Двенадцатый, расчёт закончен.

C>
Y>>        /// 222222222222222222
Y>>        m_t::iterator mi = m.begin()
Y>>                   , mie = --m.end();
Y>>        while (mi != mie)
Y>>        {
Y>>            m_t::iterator p = mi++;
Y>>            (*p).second->Move();
Y>>        }
Y>>        (*mie).second->Move();
C>

C>О ужас. Я это даже представить себе не могу, буду рисовать.
C>
C>// исходное положение
C>  1   2   3   4   5   6   7   8   9  10  11  12
C> x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
C>^  |
C>|  |             .------.
C>|  v             v      |
C>|  .-x_X----------------|------------.
C>|  |        |       |   *    |       |
C>|  | owner_ | first | second | name_ |
C>'----*      |   1   |        |   *   |
C>   '--------------------^--------|---'
C>                        |        |
C>                        '--------'
C>// остальных зомби разрисовывать не буду
C>// порядок полей не соответствует реальному

C>------------------------------------------------
C>// сразу после входа в тело цикла
C>  1   2   3   4   5   6   7   8   9  10  11  12
C> x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x

C>^mi                                         ^mie
C>------------------------------------------------
C>// m_t::iterator p = mi++;
C>  1   2   3   4   5   6   7   8   9  10  11  12
C> x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x

C>^p  ^mi                                     ^mie
C>------------------------------------------------
C>// (*p).second->Move();
C>//            owner_.erase(first);
.--->> 2   3   4   5   6   7   8   9  10  11  12
C>|    x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
C>|
C>|   ^mi                                     ^mie
C>|
C>|                .------.
C>|                v      |
C>|  .-x_X----------------|------------.
C>|  |        |       |   *    |       |
C>|  | owner_ | first | second | name_ |
C>'----*      |   1   |        |   *   |
C>   '--------------------^--------|---'
C>                        |        |
C>                        '--------'

C>------------------------------------------------
C>//            name_ += 512;
.--->> 2   3   4   5   6   7   8   9  10  11  12
C>|    x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
C>|
C>|   ^mi                                     ^mie
C>|
C>|                .------.
C>|                v      |
C>|  .-x_X----------------|------------.
C>|  |        |       |   *    |       |
C>|  | owner_ | first | second | name_ |
C>'----*      |  513  |        |   *   |
C>   '--------------------^--------|---'
C>                        |        |
C>                        '--------'

C>------------------------------------------------
C>//            owner_.insert(*this);
.--->> 2   3   4   5   6   7   8   9  10  11  12  513
C>|    x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
C>|                                                 |
C>|   ^mi                                     ^mie  |
C>|                                                 |
C>|                .--------------------------------'
C>|                v      |
C>|  .-x_X----------------|------------.
C>|  |        |       |   *    |       |
C>|  | owner_ | first | second | name_ |
C>'----*      |  513  |        |   *   |
C>   '--------------------^--------|---'
C>                        |        |
C>                        '--------'
C>------------------------------------------------
C>

C>Это всё, конечно, в предположении, что трупы каким-то неведомым образом продолжают не тухнуть. Потому что, будь я компилятор, я бы уже второго Paired положил на место уже мёртвого первого.
C>И все временные переменные в методах erase и insert имеют полное право занять их место.
у вас ошибка. first и second будут перед owner_ и name_;

Y>>И что это за вилосипед я изобрел? И поедет ли он в дальний путь?

C>Как только на кладбище построят что-нибудь полезное, а потом попытаются в очередной раз взводом зомби покомандовать, всё и упадёт.
не ответ на вопросы.
но кстате зомбями тож можно с пользой коммандовать. и важно об этом всегда помнить )
Re[2]: какая-то чертовщина с std::map
От: yatagarasu Беларусь  
Дата: 28.11.09 13:07
Оценка:
Здравствуйте, sokel, Вы писали:

S>Здравствуйте, yatagarasu, Вы писали:


Y>>Всем привет. Давно тут не писал, так что немного стесняюсь...


Y>>Придумал я велосипед такой, хочу знать ващего мнения.

Y>>Есть класс, который наследуется от std::pair<key, указатель на самого себя>
Y>>ожидал я от него, что он будет сам себя в мапе хранить. О мапе своем все знать, и ключь свой при себе держать.

S>Посмотри на интрузивные контейнеры (boost::intrusive). Там ты как раз сможешь ноду для контейнера самодельную сделать.

S>плюсы:
S>- ключ дублироваться не будет
S>- объект к итератору кастуется
S>- содержащий контейнер можно получить по цепочке: to_iterator(obj) -> to_end_iterator(iterator) -> container_from_end(end_iterator)

S>Только вот аллокатор будет внешним.


вот какого монстра я в итоге родил.
#include "fwd.h"

#include <algorithm>

#include <boost/bind.hpp>
#include <boost/intrusive/set.hpp>

namespace test
{
    template <typename V, typename P>
    struct key_wrapper
    {
        V value_;
        P &this_;
        typename P::container_t &owner_;


        key_wrapper(const V &v, P &p, typename P::container_t &c)
            : value_(v)
            , this_(p)
            , owner_(c)
        {
        }

        key_wrapper(const key_wrapper &c, P &p)
            : value_(c.value_)
            , this_(p)
            , owner_(c.owner_)
        {
        }

        key_wrapper &operator =(const key_wrapper &c)
        {
            value_ = c.value_;

            return *this;
        }


        operator V() const
        {
            return value_;
        }

        V operator =(const V &v)
        {
            if (v != value_)
            {
                owner_.erase(this_);
                value_ = v;
                owner_.insert(this_);
            }

            return value_;
        }
    };

//    template <template <> class C>
    class Paired : public boost::intrusive::set_base_hook<>
    {
    public:
//        typedef C<Paired> container_t;
        typedef boost::intrusive::set<Paired> container_t;

    private:
        key_wrapper<int, Paired> name_;

    public:
        Paired(int i, container_t &o)
            : name_(i, *this, o)
        {
        }

        Paired(const Paired &c)
            : name_(c.name_, *this)
        {
            log_print("copy.");
        }

        Paired &operator =(const Paired &c)
        {
            name_ = c.name_;

            log_print("assign.");
            return *this;
        }

        std::string Name() const
        {
            return Number(name_);
        }

        std::string Number(int name) const
        {
            if (name < 500)
            {
                if (name == 0) return "zero";
                if (name == 1) return "one";
                if (name == 2) return "two";
                if (name == 3) return "three";
                if (name == 4) return "four";
                if (name == 5) return "five";
                if (name == 6) return "six";
                if (name == 7) return "seven";
                if (name == 8) return "eight";
                if (name == 9) return "nine";
                if (name == 10) return "ten";
                if (name == 11) return "eleven";
                if (name == 12) return "twelve";
                if (name == 13) return "thirteen";
                if (name == 14) return "fourteen";
                if (name == 15) return "fifteen";
                if (name == 16) return "sixteen";
                if (name == 17) return "seventeen";
                if (name == 18) return "eighteen";
                if (name == 19) return "nineteen";
            }
            else
            {
                return std::string("five hundred and ") + Number(name - 500);
            }

            return "none";
        }

        void Move()
        {
            name_ = name_ + 500;
        }


        friend bool operator< (const Paired &a, const Paired &b)
        {
            return a.name_ < b.name_;
        }
    };

    Paired *get_pointer(const std::pair<int, Paired *> &p)
    {
        return p.second;
    }

    //[[[cog cog.outl("class %s" % test_name)]]]
    class Map
    //[[[end]]]
    {
    public:
        //[[[cog cog.outl("%s()" % test_name)]]]
        Map()
        //[[[end]]]
        {
        }

        void test()
        {
//            typedef Paired<boost::intrusive::set> p_t;
            typedef Paired p_t;
            typedef std::vector<p_t> v_t;
            typedef boost::intrusive::set<p_t> m_t;

//            p_t<std::pair<int, void *> > p;
            v_t v;
            m_t m;

            v.push_back(p_t(1, m));
            v.push_back(p_t(2, m));
            v.push_back(p_t(3, m));
            v.push_back(p_t(4, m));
            v.push_back(p_t(5, m));
            v.push_back(p_t(6, m));
            v.push_back(p_t(7, m));
            v.push_back(p_t(8, m));
            v.push_back(p_t(9, m));
            v.push_back(p_t(10, m));
            v.push_back(p_t(11, m));
            v.push_back(p_t(12, m));

            log_print("Lets dance!\n");


            for (v_t::iterator i = v.begin(); i != v.end(); i++)
            {
                m.insert(*i);
            }


            for (m_t::iterator i = m.begin(); i != m.end(); i++)
            {
                log_print("%s\n", (*i).Name().c_str());
            }


//            std::for_each(m.begin(), m.end()
//                , boost::bind(&test::Paired::Move, _1));
//            for (m_t::iterator i = m.begin(), ie = m.end(); i != ie;)
//            {
//                m_t::iterator p = i++;
//                (*p).second->Move();
//            }
            m_t::iterator mi = m.begin()
                       , mie = --m.end();
            while (mi != mie)
            {
                m_t::iterator p = mi++;
                (*p).Move();
            }
            (*mie).Move();

            for (m_t::iterator i = m.begin(); i != m.end(); i++)
            {
                log_print("%s\n", (*i).Name().c_str());
            }

//            const int i = 0;
//            const int &ci = i;

//            std::pair<const int &, int> cip(i, i);

//            std::map<const int &, int> mip;
        }
    };
}
Re[3]: какая-то чертовщина с std::map
От: sokel Россия  
Дата: 30.11.09 07:55
Оценка: 3 (1)
Здравствуйте, yatagarasu, Вы писали:

Y>вот какого монстра я в итоге родил.


Тебе это что ли надо?:
#include <algorithm>
#include <vector>
#include <boost/intrusive/set.hpp>

struct my_obj : public boost::intrusive::set_base_hook<>
{
    int i;
    my_obj(int i): i(i) {}
    void move()
    {
        typedef boost::intrusive::set<my_obj> t_container;
        t_container::iterator it = t_container::s_iterator_to(*this);
        t_container& owner = t_container::container_from_iterator(it);
        owner.erase(it);
        i+=500;
        owner.insert(*this);
    }
    bool operator< (const my_obj &b) const { return i < b.i; }
    void print() const { printf("%d\n", i); }
};

void main()
{
    std::vector<my_obj> v;
    boost::intrusive::set<my_obj> i;
    for(int k=0; k<10; ++k) v.push_back(k);
    i.insert(v.begin(), v.end());
    std::for_each(i.begin(), i.end(), std::mem_fun_ref(&my_obj::print));
    std::for_each(v.begin(), v.end(), std::mem_fun_ref(&my_obj::move));
    std::for_each(i.begin(), i.end(), std::mem_fun_ref(&my_obj::print));
}
Re[3]: какая-то чертовщина с std::map
От: Centaur Россия  
Дата: 30.11.09 13:57
Оценка:
Здравствуйте, yatagarasu, Вы писали:

Y>>>        m.insert(Paired(1, m));

C>>Создали временный объект, он запомнил указатель на себя; срезали его в std::pair в map’е, указатель скопировался; убили временный объект — указатель в pair остался указывать на труп. Итого, к этому моменту у нас есть map, содержащий 12 указателей на трупы.
Y>ох стар стал. не помню уже. не уверен доживут ли они до закрывающей скобки }. но это прототип.

Временные объекты живут до конца полного выражения. Не дольше.

C>>О ужас. Я это даже представить себе не могу, буду рисовать.

C>>// исходное положение
C>>  1   2   3   4   5   6   7   8   9  10  11  12
C>> x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x x_x
C>>^  |
C>>|  |             .------.
C>>|  v             v      |
C>>|  .-x_X----------------|------------.
C>>|  |        |       |   *    |       |
C>>|  | owner_ | first | second | name_ |
C>>'----*      |   1   |        |   *   |
C>>   '--------------------^--------|---'
C>>                        |        |
C>>                        '--------'
C>>// остальных зомби разрисовывать не буду
C>>// порядок полей не соответствует реальному

[…]
Y>у вас ошибка. first и second будут перед owner_ и name_;

Я где-то писал, что порядок полей реальный? По-моему, наоборот.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.