Я работаю над разделом кода, который имеет много возможных мест ошибки, которые заставляют его выходить из функции рано. Библиотеки, с которыми я взаимодействую, требуют, чтобы массивы C-стиля были переданы функциям. Так, вместо вызова удаляют на массивах в каждой точке выхода, я делаю это:
void SomeFunction(int arrayLength)
{
shared_ptr<char> raiiArray(new char[arrayLength]);
pArray = raiiArray.get();
if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }
//etc.
}
Я хотел использовать unique_ptr
, но мой текущий компилятор не поддерживает его, и подсчет ссылок наверху действительно не имеет значения в этом случае.
Я просто задаюсь вопросом, есть ли у кого-либо какие-либо мысли об этой практике при взаимодействии через интерфейс с унаследованным кодом.
ОБНОВИТЕ я полностью забыл о shared_ptr
вызов delete
вместо delete []
. Я просто не видел утечек памяти и решил пойти с ним. Даже не думал для использования вектора. Так как я копался в новом (для меня) C++ в последнее время, я думаю, что у меня есть случай, "Если единственный инструмент, который Вы имеете, является молотком, все похоже на гвоздь". синдром. Спасибо за обратную связь.
UPDATE2 я полагал, что изменю вопрос и предоставлю ответ для создания его немного более ценным кому-то делающему ту же ошибку, что я сделал. Хотя существуют альтернативы как scoped_array
, shared_array
и vector
, можно использовать a shared_ptr
для управления объемом массива (но после этого я понятия не имею, почему я хотел бы к):
template <typename T>
class ArrayDeleter
{
public:
void operator () (T* d) const
{
delete [] d;
}
};
void SomeFunction(int arrayLength)
{
shared_ptr<char> raiiArray(new char[arrayLength], ArrayDeleter<char>());
pArray = raiiArray.get();
if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }
//etc.
}
Не используйте shared_ptr
или scoped_ptr
для хранения указателей на динамически выделяемые массивы. shared_ptr и scoped_ptr используют delete ptr;
для очистки, когда указатель больше не ссылается / выходит за пределы области видимости, что вызывает неопределенное поведение для динамически выделяемого массива. Вместо этого используйте shared_array или scoped_array, которые правильно используют delete [] ptr;
при уничтожении.
Чтобы ответить на ваш вопрос, если вы не собираетесь передавать интеллектуальный указатель, используйте scoped_array
, так как у него меньше накладных расходов, чем у shared_array
.
В качестве альтернативы можно использовать std :: vector
в качестве хранилища массива (для векторов гарантировано непрерывное выделение памяти).
Я настоятельно рекомендую просто использовать std :: vector
. Элементы в векторах
размещены в куче и будут удалены, когда вектор
выйдет за пределы области видимости, где бы вы ни вышли из функции.
Чтобы передать вектор
в унаследованный код, требующий массивов в стиле C, просто передайте & vectorName [0]
. Гарантируется, что элементы непрерывны в памяти.
Это
shared_ptr<char*> raiiArray(new char[arrayLength]);
не очень хорошая практика, она вызывает неопределенное поведение, так как вы выделяете с помощью оператора new[]
, но shared_ptr
использует оператор delete
для освобождения памяти. Правильнее всего использовать boost::shared_array
или добавить собственный удалитель.
Используйте boost :: scoped_array
или даже лучше std :: vector
, если вы имеете дело с массивом.