станд.:: вектор:: ясный () в конструкторе и деструкторе

Codejacked покрывает три различных метода о том, как сравнить документы слова.

19
задан dimba 19 October 2009 в 20:48
поделиться

7 ответов

Судя по всему, люди, написавшие этот код, были теми, кто что-то упустил. Единственный раз, когда имело бы смысл вызывать clear () в ctor или dtor, было бы в середине другого кода. Например, оператор может прочитать некоторые данные, обработать их, а затем прочитать дополнительные данные. В таком случае, вероятно, быстрее использовать один контейнер для данных по мере их чтения и очищать каждый раз, чем создавать новый контейнер на каждой итерации.

20
ответ дан 30 November 2019 в 02:24
поделиться

Нет, вы ничего не упустили. Я подозреваю, что это (безобидное) программирование вуду, что-то вроде установки указателя на null после его освобождения или случайного вызова repaint / revalidate в коде графического интерфейса. Программист вспоминает, что это помогало с какой-то ошибкой в ​​прошлом, и теперь добавляет ее без надобности «на всякий случай». Кто знает, может, это поможет. Вуду.

24
ответ дан 30 November 2019 в 02:24
поделиться
  1. Совершенно небезопасно очищать содержимое stl-контейнера в конструкторе
  2. Небезопасно очищать содержимое stl-контейнера в деструкторе ЕСЛИ контейнер не содержит указатель. Если указатель был создан с использованием new , его все равно необходимо сначала удалить . После этого по-прежнему нет необходимости очищать контейнер.

Учтите следующее:

#define BOOST_TEST_MODULE StlContainers
#define BOOST_LIB_DIAGNOSTIC

#include <boost/test/unit_test.hpp>
#include <boost/assign.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/vector.hpp>

#include <vector>

using namespace boost::assign;
using namespace std;

const vector<int> my_ints_vector = list_of(0)(1)(1)(2)(3)(5)(8)(13)(21)(34);

struct ScopedStruct1
{
        ScopedStruct1(const vector<int> & v) : m_v(v) {}
        ~ScopedStruct1() {}
    private :
        vector<int> m_v;
};

class A 
{ 
    public :
        A(int i) : m_i(i) {}
        ~A() {}
    private :
        int m_i;
};

struct ScopedStruct2
{
    ScopedStruct2() {}
    ~ScopedStruct2() { for(vector<A*>::iterator it = m_v.begin(); it != m_v.end(); ++it) delete *it; }

    vector<A*> m_v;
};

struct ScopedStruct3
{
    ScopedStruct3() {}
    ~ScopedStruct3() { /* no deletion */ }

    vector<A*> m_v;
};

BOOST_AUTO_TEST_CASE(StlContainer_storing_something_simple)
{
    ScopedStruct1 str(my_ints_vector);
}

BOOST_AUTO_TEST_CASE(StlContainer_storing_pointers_with_delete)
{
    ScopedStruct2 str;
    for(int i = 0; i < 10; i++)
        str.m_v.push_back(new A(i));
}

BOOST_AUTO_TEST_CASE(StlContainer_storing_pointers_without_delete)
{
    ScopedStruct3 str;
    for(int i = 0; i < 10; i++)
        str.m_v.push_back(new A(i));
}

Используя структуру boost unit_test, я создал 3 тестовых примера. Фреймворк unit_test хорош, потому что он отслеживает утечки памяти. Вы заметите, что 1-й и 2-й тестовые примеры не вызывают утечек памяти, но 3-й случай вызывает, потому что содержимое вектора не удаляется.

7
ответ дан 30 November 2019 в 02:24
поделиться

Нет, ты прав. Если в конструкторе (или конструкторе базовых классов) нет каких-то дополнительных дел, которые требуют этого, но шансы очень низкие ...

Позднее редактировать

В случае деструктора, одна из самых распространенных ошибок I Видно, что некоторые люди предполагают, что метод clear также будет вызывать удаление векторов указателей (vector), что, конечно, не так

5
ответ дан 30 November 2019 в 02:24
поделиться

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

Конечно, лучше структурировать код так, чтобы этого не требовалось; однако это вполне объяснимая причина.

2
ответ дан 30 November 2019 в 02:24
поделиться

Конечно, нужно вызвать clear () или resize (0) или эквивалентный say (std :: _ Destroy_range (...) в деструкторе перед освобождением.

Освобождение выполнено через allocator :: deallocate , который НЕ запускает деструкторы . Он просто освобождает память.

clear () эквивалентен resize (0), который запускает деструкторы для объектов first size () в выделенном buffer

НЕ только выделенные указатели, дескрипторы файлов, удерживаемые мьютексы, все другие восстанавливаемые ресурсы, удерживаемые объектом. Деструкторы ДОЛЖНЫ запускаться. Перед созданием экземпляра шаблон не знает, что деструктор тривиален. Если деструктор тривиален, ТОГДА он оптимизируется ПОСЛЕ создания экземпляра

-5
ответ дан 30 November 2019 в 02:24
поделиться

Несмотря на то, что было сказано до сих пор, существует по крайней мере один сценарий, когда может потребоваться явный вызов clear в деструкторе.

Представьте себе ситуацию, когда у уничтожаемого объекта есть несколько подобъектов-членов, которые требуют определенного порядка уничтожения, т.е. подобъекты каким-то образом зависят друг от друга, и неправильный порядок их разрушения приведет к нежелательным результатам. Как вы, наверное, знаете, порядок уничтожения подобъекта члена (а также инициализации члена) определяется порядком объявления членов в определении класса. Так, один из способов добиться правильного порядка уничтожения - это расположить объявления членов соответствующим образом. Однако, во-первых, это не очень хорошее решение с точки зрения обслуживания. Во-вторых, желаемый порядок уничтожения может зависеть от некоторых условий выполнения. В-третьих, желаемый порядок уничтожения может противоречить желаемому порядку инициализации. Все это означает, что может быть невозможно (или неразумно) указать правильный порядок уничтожения, переупорядочив объявления.

Разумным подходом в этом случае может быть очистка некоторых критических подобъектов-членов вручную, вызывая их методы clean или подобные, до тех пор, пока зависимость порядка уничтожения не «исчезнет». Я бы предположил,

2
ответ дан 30 November 2019 в 02:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: