Получение внешнего объекта класса из внутреннего объекта класса в C ++ - PullRequest
0 голосов
/ 10 июня 2018

ВОПРОС

Я видел ЭТОТ вопрос по Java, который позволяет получить указатель на Внешний объект изнутри Вложенного объекта .

Но как вы могли бы реализовать это в C ++ ?

Неудовлетворительные решения:

Хранение указателя на каждый объект : (не эффективно для использования памяти)

class Outer {
private:
    int i;
    class Inner {
        int j;
        Outer *outer;
    };
    Inner items[1000];
};

Заключение массива в класс : (добавляет ненужную (?) сложность)

class Outer {
private:
    int i;
    class Inner_array {
        class Inner {
            int j;
        };
        Inner items[1000];

        // Build an interface around the array
        typedef Inner (&array)[1000]; 
        operator array();
        // etc...
    };

    Inner items[1000];
    Outer *outer;
};

1 Ответ

0 голосов
/ 10 июня 2018

Вот одна идея сэкономить место:

struct Outer {
    int i;

    struct Inner {
        int j;
        uint16_t where;

        Outer& outer() {
            Inner* first = this - where;
            char* addr = reinterpret_cast<char*>(first) - offsetof(Outer, items);
            return *reinterpret_cast<Outer*>(addr);
        }
    };

    Inner items[1000];

    Outer() {
        for (uint16_t ii = 0; ii < 1000; ++ii)
            items[ii].where = ii;
    }
};

Если вы работаете на 64-битной машине с 32-битными целыми числами, это уменьшает sizeof(Inner) с 16 до 8 байт без упаковки, илиУпаковка от 12 до 6 байт.

Если вы хотите сэкономить еще больше места, вы можете сделать это:

struct Outer {
    int i;

    struct Inner {
        int j;

        Outer& outer() {
            Inner* sentinel = this;
            while (sentinel.j != INT_MIN)
                --sentinel;
            char* addr = reinterpret_cast<char*>(sentinel) - offsetof(Outer, sentinel);
            return *reinterpret_cast<Outer*>(addr);
        }
    };

    Inner sentinel = {INT_MIN};
    Inner items[1000];
};

Но тогда outer() - это O (n) вместо O (1), и вы должны быть уверены, что INT_MIN (или некоторое значение часового) никогда не используется в items.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...