Можно ли использовать shared_ptr для RAII массивов C-стиля?

Я работаю над разделом кода, который имеет много возможных мест ошибки, которые заставляют его выходить из функции рано. Библиотеки, с которыми я взаимодействую, требуют, чтобы массивы 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.
    }
26
задан bsruth 16 July 2010 в 16:42
поделиться

5 ответов

Не используйте shared_ptr или scoped_ptr для хранения указателей на динамически выделяемые массивы. shared_ptr и scoped_ptr используют delete ptr; для очистки, когда указатель больше не ссылается / выходит за пределы области видимости, что вызывает неопределенное поведение для динамически выделяемого массива. Вместо этого используйте shared_array или scoped_array, которые правильно используют delete [] ptr; при уничтожении.

Чтобы ответить на ваш вопрос, если вы не собираетесь передавать интеллектуальный указатель, используйте scoped_array , так как у него меньше накладных расходов, чем у shared_array .

В качестве альтернативы можно использовать std :: vector в качестве хранилища массива (для векторов гарантировано непрерывное выделение памяти).

27
ответ дан 28 November 2019 в 06:37
поделиться

Я настоятельно рекомендую просто использовать std :: vector . Элементы в векторах размещены в куче и будут удалены, когда вектор выйдет за пределы области видимости, где бы вы ни вышли из функции.

Чтобы передать вектор в унаследованный код, требующий массивов в стиле C, просто передайте & vectorName [0] . Гарантируется, что элементы непрерывны в памяти.

7
ответ дан 28 November 2019 в 06:37
поделиться

Для этого существует boost::scoped_ptr -.

5
ответ дан 28 November 2019 в 06:37
поделиться

Это

shared_ptr<char*> raiiArray(new char[arrayLength]);

не очень хорошая практика, она вызывает неопределенное поведение, так как вы выделяете с помощью оператора new[], но shared_ptr использует оператор delete для освобождения памяти. Правильнее всего использовать boost::shared_array или добавить собственный удалитель.

3
ответ дан 28 November 2019 в 06:37
поделиться

Используйте boost :: scoped_array или даже лучше std :: vector , если вы имеете дело с массивом.

15
ответ дан 28 November 2019 в 06:37
поделиться
Другие вопросы по тегам:

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