2009-11-23 4 views
5
class MyClass 
{ 
}; 

void foo 
{ 
    MyClass arr[10]; 
} 

Я хочу знать порядок уничтожения объектов массива при возврате функции.Порядок уничтожения для массива объектов

Я прочитал его более эффективным C++ об этом, и он говорит, что деструктор вызываются в обратном порядке к тому, что порядка конструктора следующим образом:

for(int i = 9 ; i >= 0 ;i--) 
{ 
    arr[i].MyClass::~MyClass(); 
} 

Может кто-нибудь сказать мне причину этого?

ответ

2

Это продолжение обратного порядка, связанного с деструктором. Когда объекты, выделенные для стека, уничтожаются, они выполняются в обратном порядке для облегчения RAII. Хотя это и не обязательно для элементов массива (все они построены с помощью конструкторов по умолчанию и любой порядок построения/уничтожения будет делать) то же самое делается с ними только для согласованности.

+1

все они построены с конструкторами по умолчанию, и любой порядок построения/разрушения будет выполняться ». Поскольку конструктор no-arg может обращаться к глобальным переменным (например, по статике классов), он имеет значение для результирующего массива, поэтому я не совсем уверен, что вы подразумеваете под «любым приказом» - только один заказ соответствует стандарту 12.6. Стандарт мог бы сказать, что порядок был определен по реализации или мог бы сказать, что они построены в обратном порядке числа различных простых факторов в индексе со связями, определяемыми цифрой суммы в базе 7 ;-) –

0

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

+0

Если arr [n] относится к элементу arr [n + 1] в своем DTor, вы можете попасть в неприятности Однако, с моей точки зрения, я не могу представить себе ситуацию в реальном мире, где это может быть необходимо. – foraidt

+0

@mxp. Полностью согласен, но если каждый элемент массива зависит, по крайней мере, от один из элементов массива, порядок уничтожения элементов массива будет лишь незначительной проблемой. – jrbjazz

2

вы имеете в виду в более эффективном C++ информация относится к объектам, которые содержат несколько другого объекта, так как в этом случае:

class Foo { 
    private: 
    Bar bar_1; 
    Bar bar_2; 

    public: 
    Foo() : bar_1(), bar_2() {} 
}; 

В приведенном выше примере, вы будете иметь bar_1 построен первый , а затем bar_2. Когда объект класса Foo затем уничтожается, сначала начинается уничтожение bar_2, затем bar_1. Об этом говорит Скотт Мейерс.

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

Что касается того, каким образом элементы массива будут уничтожены, я бы не удивился, если это зависит от реализации. У вас также будет оптимизация, играющая здесь роль (например, массив POD можно уничтожить, просто освободив его память, а также объект, который состоит исключительно из POD). Все вышеперечисленное может повлиять на порядок, в котором элементы массива будут уничтожены.

Мне было бы интересно узнать, почему вам нужно знать порядок, в котором элементы массива уничтожаются (кроме технического любопытства, которое было бы веской причиной ИМХО). Если это потому, что есть зависимости между элементами массива, я думаю, что структура данных может потребоваться пересмотреть.

1

Любой заказ будет, действительно. Два очевидных выбора, конечно, по порядку или в обратном порядке. Однако в этом случае ни один из разработчиков компилятора не счел нужным оставить эту зависимость от реализации. Следовательно, был выбран мандат на обратный порядок (как указано в sharptooth, распространяющем обычное поведение LIFO)

0

Вы не указали, какую страницу в книге Мейера вы имеете в виду, но я согласен с Тимо Geusch, что объяснение похоже, что это относится к тому, что конструкторы и деструкторы вызываются в соответствии с наследованием.

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

Контрольный код распечатывает количество объектов от 0 до 9 при построении, затем от 9 до 0 при уничтожении экземпляров. (Это было проверено с g++-4.2 на Mac OS X.)

#include <iostream> 

class MyClass 
{ 
public: 

    MyClass() 
    { 
     mCounter = kInstanceCount++; 
     std::cout << "+++ MyClass() " << mCounter << std::endl; 
    } 

    ~MyClass() 
    { 
     std::cout << "--- MyClass() " << mCounter << std::endl; 
    } 

private: 
    unsigned   mCounter; 
    static unsigned  kInstanceCount; 
}; 

unsigned MyClass::kInstanceCount = 0; 

int main() 
{ 
    MyClass arr[10]; 
    return 0; 
} 

Вы должны были бы проверить Стандарт C++, так как я не 100% уверен, что это не деталь реализации (как это часто бывает) , и в этом случае вы не хотите полагаться на это поведение.

Обратите также внимание на то, что не так часто создавать массив фактических экземпляров объектов на основе стека. Вы, скорее всего, будете использовать std::vector или, может быть, использовать интеллектуальные указатели для объектов, выделенных кучей.

Смежные вопросы