C ++ самоссылающийся класс - PullRequest
2 голосов
/ 09 марта 2012

Я должен признать, что мой C ++ немного ржавый. В проекте я пытаюсь создать вектор классов и использовать их. Существует проблема, потому что я хочу идентифицировать каждую запись вектора с уникальным указателем на него для быстрого доступа, но он не работает. Вот минимальный пример моей проблемы:

#include <iostream>
#include <vector>

class Foo{
public:
Foo() { ptr = this; }
~Foo() {}
Foo * ptr;
};

int main()
{
std::vector<Foo> vec;
for(unsigned int i = 0; i < 2; ++i)
  vec.push_back(Foo());
for(unsigned int i = 0; i < vec.size(); ++i)
 std::cout << "Object Self-Pointer: " << std::hex << reinterpret_cast<unsigned int>(vec[i].ptr) << std::endl; 
}

Фактический объем производства:

Object Self-Pointer: bfbebc18
Object Self-Pointer: bfbebc18

Предполагаемая мощность:

Object Self-Pointer: bfbebc18
Object Self-Pointer: bfbebc1c

(некоторые указатели на реальные объекты).

Надеюсь, вы поможете мне с этим вопросом, заранее спасибо.

Ответы [ 4 ]

10 голосов
/ 09 марта 2012

Когда вы делаете это:

vec.push_back(Foo());

Создается новый временный объект Foo, но каждый раз, когда он создается по одному и тому же адресу (потому что он создается в стеке, а указатель стека являетсятак же).Таким образом, указатель this и, следовательно, ptr член каждого из этих экземпляров одинаковы.

Когда вы добавляете каждый экземпляр в вектор, вызывается конструктор копирования по умолчанию , поэтому элемент ptr копируется, и, следовательно, все экземпляры в векторе имеют одинаковое значение.

3 голосов
/ 09 марта 2012

std :: vector хранит копии объекта (необходимо, чтобы тип объекта создавался как копия).В этом случае конструктор копирования Foo автоматически генерируется компилятором.

Поэтому, когда вы выполняете push_back (Foo ()), вы делаете:

1) Create a Foo() object. Set ptr to bfbebc18
2) Copy it, and put it into vector<Foo>
3) Delete the original Foo from which it came
4) Create a new Foo() object. Set ptr to bfbebc18 (the same location is used because it's temporary)
5) Copy it and put it into vector<Foo>
1 голос
/ 09 марта 2012

Как уже упоминалось, проблема заключается в том, что push_back помещает копию объекта в стек, который создается с помощью конструктора копирования, который выполняет членское копирование переменной-члена.

Один из способов решения этой проблемы - определить конструктор копирования, который будет делать то, что вы хотите;Например:

Foo(const Foo& rhs) { ptr = this;}

Работая с этим, я получил вывод:

Object Self-Pointer: 4b0308
Object Self-Pointer: 4b030c
1 голос
/ 09 марта 2012

Когда вы вызываете push_back(Foo()), объект создается, а затем vector получает копию этого объекта.Поскольку Foo использует конструктор копирования по умолчанию, он будет хранить указатель this временного объекта, созданного Foo().Адрес временного объекта кажется одинаковым на обеих итерациях цикла.

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