Опасно ли, когда локальные переменные ссылаются на другие локальные переменные? - PullRequest
2 голосов
/ 22 марта 2012

Возьмите эти два класса, например:

struct Owned {
    Owned() : i() { }

    void print() { cout << ++i << endl; }

    int i;
};

struct Owner {
    Owner(Owned& o) : o(o) { }

    Owned& o;

    ~Owner() { o.print(); }
};

Опасно ли использовать их таким образом?

int main() {
    Owned owned;
    Owner owner(owned);
}

Похоже, что в зависимости от порядка, в котором они уничтожены, это может заставить деструктор owner вызвать функцию для уничтоженного owned. Определен ли порядок уничтожения локальных переменных и как можно создать ситуацию, когда два экземпляра ссылаются друг на друга?

Простите, если это общеизвестно, хотя я нигде не читал об этом.

Ответы [ 4 ]

5 голосов
/ 22 марта 2012

Локальные переменные уничтожаются в порядке, обратном созданию.В вашем случае у вас все в порядке, поскольку owner всегда будет уничтожено до owned.

§6.6 [stmt.jump] p2

При выходе из области действия (как выполнено),объекты с автоматическим сроком хранения (3.7.3), построенные в этой области, уничтожаются в порядке, обратном их построению.

Однако следует соблюдать осторожность, если вы можете переназначить принадлежащего участникапосле строительства.

как вы можете создать ситуацию, когда два экземпляра ссылаются друг на друга?

Не позволяйте им обращаться друг к другу в своем деструкторе.Или проясните, кто именно будет уничтожен первым, может быть, с помощью обратного вызова или пропущенного флага.Пример:

struct two;
struct one{
  two* other;

  one(two* o = nullptr) : other(o) {}
  ~one(){ if(other) other.other = nullptr; }
};

struct two{
  one* other;
  two(one* o = nullptr) : other(o) {}
  ~one(){ if(other) other.other = nullptr; } 
};

Это гарантирует, что оба объекта никогда не ссылаются на несуществующий.

В любом случае взаимно ссылающиеся объекты очень редки.

1 голос
/ 22 марта 2012

То, что вы написали, в любом случае не опасно, переменные в той же области видимости в C ++ уничтожаются определенным образом (в обратном порядке). Что-то подобное, однако, опасно,

int main() {
    Owner owner();
    {
        Owned owned;
        owner.setOwned(owned);
    }

    owner.doSomethingWithOwned();
}

Поскольку принадлежащий больше не существует, он был вынужден выйти за рамки. Это также относится к установке локальных переменных в качестве ссылок в объектах в куче.

1 голос
/ 22 марта 2012

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

0 голосов
/ 22 марта 2012

Это безопасно, локальные объекты уничтожаются в порядке, обратном их созданию.

...