2010-07-14 3 views
2

Это хорошая практика? Или я должен просто заменить блок кода между { и } функцией? Он может быть повторно использован (я признаю), но моя единственная мотивация для этого заключается в освобождении colsum, так как это огромный и не требуется, чтобы я мог освободить выделенную память.Освобождение выделенной памяти

vector<double> C; 
{ 
    vector<double> colsum; 
    A.col_sum(colsum); 
    C = At*colsum; 
} 
doSomething(C); 
+0

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

+0

Для тех, кто считает, что это не сработает, см. Http://stackoverflow.com/questions/500006/what-is-the-purpose-of-anonymous-blocks-in-c-style-languages ​​ – bshields

+0

Кому нужны функции? ?? –

ответ

13

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

+1

+1: для предложения разбить его в любом случае - делает для более многоразового/читаемого кода :-) –

+0

@bshileds: Основная цель, как указано в вопросе, - заставить освободить вектор. Это то, что вы имели в виду (кажется, это из ваших комментариев)? – Jacob

+1

@Jacob Я понимаю ваше намерение, и я говорю, что это правильный способ сделать это, более чистый, чем использование функции «swap», как это было предложено другими ответами, потому что он использует RAII. Это место, особенно для обертывания кода с помощью объекта 'Mutex' или чего-то подобного. НО вы просто должны быть осторожны, потому что, используя скобки, вы подтверждаете, что у вас есть этот дополнительный набор переменных, которые вы хотите сохранить отдельно и использовать в своей области для выполнения промежуточной обработки. У вас есть все основания для того, чтобы не блокировать свою собственную функцию, потому что она действительно пахнет. – bshields

5

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

РЕДАКТИРОВАТЬ

Что касается динамического освобождения, он должен будет быть высвобождены в той или иной точке (в частности, конец функции). Вы ничего не теряете, оставив выделенную память, пока не захотите выделить больше, и этого недостаточно. Является ли точное время, когда это освобождение происходит, действительно что-то нужно беспокоить, прежде чем вы столкнетесь с какой-то проблемой?

/EDIT

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

Если вы хотите реорганизовать свой код, сделайте это ради ясности, а не производительности.

+3

Не совсем. Когда 'colsum' выходит за пределы области видимости, он освобождает память, связанную с ней. – Jacob

+1

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

+0

Оставляя память, выделенную до окончания функции, на самом деле ничего не повредит. Если вы обнаружите, что на самом деле вы столкнулись с ситуациями с низкой памятью, ваша оптимизация является зрелой. jMerliN также делает хороший вывод. Я не уверен, что есть какая-либо гарантия того, что освобождение произойдет в закрывающей скобке. Он может дождаться окончания функции в любом случае. – Cogwheel

3

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

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

3

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

vector<double> C; 
vector<double> colsum; 
A.col_sum(colsum); 
C = At*colsum; 
    std::vector<double>().swap(colsum); 
doSomething(C); 

Это создаст временный вектор и поменять местами содержимое с большим вектором. В конце инструкции временное будет уничтожено и память будет выпущена. У вас останется пустой вектор.

Обратите внимание, что colsum.resize(0) и colsum.clear() не нужно освобождать доступную память, и во многих случаях они не предполагают, что если вектор до этого возрастает до этого размера, скорее всего, он сделает это снова.

+0

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

+0

Чтобы очистить вектор, я использовал бы трюк подкачки, поскольку это обычная идиома, но я согласен, что область имеет свои преимущества. Первый из них состоит в том, что идентификатор может быть повторно использован, а второй - для типов, где нет эквивалента 'swap' (например, блокированные блокировки)' {lock (mutex); ....} ' –

0

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

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