Смысл статики в C ++ - PullRequest
       1

Смысл статики в C ++

4 голосов
/ 11 ноября 2010

Мне показалось, что я неплохо справляюсь с C ++, оказывается, что нет. Предыдущий вопрос, который я задал: C ++ const lvalue ссылки имел следующий код в одном из ответов:

<code>
<code>#include <iostream></code>
using namespace std;</p>

<p>int& GenX(bool reset)
{
    static int* x = new int;
    *x = 100;
    if (reset)
    {
        delete x;
        x = new int;
        *x = 200;
    }
    return *x;
}</p>

<p>class YStore
{
public:
    YStore(int& x);
    int& getX() { return my_x; }
private:
    int& my_x;
};</p>

<p>YStore::YStore(int& x)
 : my_x(x)
{
}</p>

<p>int main()
{
    YStore Y(GenX(false));
    cout << "X: " << Y.getX() << endl;
    GenX(true); // side-effect in Y
    cout << "X: " << Y.getX() << endl;
    return 0;
}

Приведенный выше код выводит X: 100, X: 200. Я не понимаю почему. Я немного поиграл с ним и добавил еще один вывод, а именно: cout перед удалением x; и клоут после нового х; в блоке управления сбросом.

То, что я получил, было: перед удалением: 0x92ee018 после нового: 0x92ee018

Итак, я подумал, что static молча провалил обновление x, а второй getX проигрывал (после удаления) неинициализированную память; Чтобы проверить это, я добавил x = 0; после удаления, перед новым и другим cout, чтобы гарантировать, что x действительно был сброшен до 0. Это было.

Итак, что здесь происходит? Как получилось, что new возвращает тот же блок памяти, что и предыдущее удаление, предположительно free'd? Это только потому, что именно это решил сделать менеджер памяти ОС, или в статических функциях чего-то не хватает?

Спасибо!

Ответы [ 5 ]

8 голосов
/ 11 ноября 2010

Это именно то, что решил сделать менеджер памяти.Если вы думаете об этом, это имеет большой смысл: вы только что освободили int, а затем снова просите int ... почему диспетчер памяти не должен вернуть вам int, который вы только что освободили?

Более технически то, что, вероятно, происходит, когда вы delete, это то, что менеджер памяти добавляет блок памяти, который вы освободили, в начало списка свободных.Затем, когда вы вызываете new, диспетчер памяти просматривает свой свободный список и обнаруживает блок подходящего размера в самой первой записи.

Для получения дополнительной информации о динамическом выделении памяти см. «Внутреннее хранилищераспределение ".

1 голос
/ 11 ноября 2010

Я проверяю ваш код в VC2008, вывод: X: 100, X: -17221323. Я думаю, что причина в том, что статический х освобожден. я думаю, что мой тест является разумным.

1 голос
/ 11 ноября 2010

На ваш первый вопрос:

X: 100, X: 200.Я не понимаю, почему.

Поскольку Y.my_x - это просто ссылка на static *x в GenX, это именно то, что и должно быть - оба ссылаются на один и тот же адресв памяти, и когда вы изменяете содержимое * x, вы получаете побочный эффект.

1 голос
/ 11 ноября 2010

Вы обращаетесь к блоку памяти, который освобожден. По стандарту c ++ это неопределенное поведение, поэтому может произойти все что угодно.

EDIT

Думаю, мне нужно нарисовать:

  1. Вы выделяете память для int и передаете объект, выделенный в куче, конструктору Y, который сохраняет его в ссылке
  2. затем вы освобождаете эту память, но ваш объект Y все еще содержит ссылку на освобожденный объект
  3. затем вы снова получаете доступ к объекту Y, который содержит недопустимую ссылку, ссылающуюся на освобожденный объект, и полученный вами результат является результатом неопределенного поведения.

EDIT2

Ответ на вопрос: реализация определена. Компилятор может создавать новый объект в любом месте, которое ему нравится.

0 голосов
/ 11 ноября 2010

Это имеет смысл для кода.

Помните, что статическим является ваш указатель, поэтому при вводе этой функции во второй раз вам не нужно создавать новый указатель, но всегдавведя эту функцию, вы создаете новый int для указателя, на который указывает указатель.

Вы также, вероятно, находитесь в режиме отладки, где тратится немного больше времени, давая вам хорошие адреса.

Именно поэтомуint, на который указывает ваш указатель, находится в том же пространстве, вероятно, просто из-за чистой удачи, и вы не объявляете какие-либо другие переменные перед этим, поэтому то же пространство в памяти все еще свободно

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