Переменная Scoping в методе и ее сохранение в C ++ - PullRequest
2 голосов
/ 15 мая 2010

Рассмотрим следующий открытый метод, который добавляет целочисленную переменную к вектору целых чисел (закрытый член) в классе в C ++.

KoolMethod()
{
  int x;
  x = 10;
  KoolList.Add(x);
}
Vector<int>KoolList;

Но действительно ли это дополнение к вектору ??? При вызове метода он создает локальную переменную. Область действия этой локальной переменной заканчивается в тот момент, когда контроль выполнения покидает метод. А поскольку эта локальная переменная размещается в стеке (при вызове метода), любой член KoolList указывает на недопустимое место в памяти в освобожденном стеке, которое может содержать или не содержать ожидаемое значение x. Это точное описание вышеуказанного механизма?

Есть ли необходимость в создании int в кучном хранилище с использованием оператора «new» каждый раз, когда необходимо добавить значение в вектор, как описано ниже ????:

KoolMethod()
{
  int *x = new int();
  *x = 10;
  KoolList.Add(x);
}
 Vector<int*>KoolList;   

Ответы [ 4 ]

2 голосов
/ 15 мая 2010

A Vector<int> (по крайней мере, если std::vector) сохраняет элементы по значению, поэтому при вызове add() создается копия объекта параметра и сохраняется эта копия в массиве. Следовательно, не имеет значения, что происходит с исходным объектом, копия в векторе жива, пока сам вектор (конечно, если явно не удален или перезаписан).

A Vector<X*> может быть более подходящим, если вы

  • хочу работать с полиморфными X объектами,
  • не хочет копировать объекты X, например. потому что это дорого или запрещено,
  • хочет поделиться одними и теми же объектами между разными сторонами.

Конечно, ничего из этого не относится к int, только к реальным объектам. Тем не менее, лучше хранить умные указатели в векторе, а не в необработанных указателях, например vector<auto_ptr<X> > или vector<shared_ptr<X> >. Они автоматически управляют удалением объектов для вас.

2 голосов
/ 15 мая 2010

Но является ли это допустимым дополнением к вектору?

Да, вектор (стандартная библиотека) хранит копии.

Есть ли необходимость всоздание int в памяти кучи с помощью оператора «new»

Если вы не хотите, чтобы объекты копировались или работали с полиморфными объектами (см. Object Slicing ), выбуду использовать указатели.В этом случае желательно избегать ручного освобождения и использовать обертки (умные указатели или контейнеры указателей), чтобы вернуть безопасность исключений.

0 голосов
/ 15 мая 2010

Подумайте об этом: при добавлении к стандартному вектору создается копия добавленного объекта.

В первом фрагменте кода вы используете вектор целых чисел, поэтому вы добавите копию локального целого и все будет в порядке.

Во втором фрагменте кода вы используете вектор указателей на int, поэтому вы добавите копию указателя ( не копию объекта, на который указывает указатель). Поскольку объект, на который указывает указатель, будет оставаться действительным после выхода из метода (он инициализируется с помощью оператора new и нигде не удаляется), все будет в порядке.

0 голосов
/ 15 мая 2010

Если вы создадите вектор целых, он не будет вектором указателей. Целые числа хранятся по значению, без указателей, и поэтому у вас не возникнет проблем с недействительными адресами памяти.

Вот пример кода, который может вызвать такую ​​проблему:

std::vector<int *> my_list;

void a_method() {
    int value = 2; // allocated on the stack
    my_list.push_back(&value); // pushes a pointer to the stack... not good
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...