2013-02-12 2 views
2

Вот в основном то, что я хочу сделать:Как пройти unique_ptr <char[]> к функции использовать

SerialPort::ReadBytes(int32& errcode, Message::string& msg, uint32 num) 
{ 
    DWORD numBytesRead = 0; 
    LPDWORD pNumBytesRead = &numBytesRead; 
    errcode = 0;   

    std::unique_ptr <char[]> buff (new char[num]); 
    // ^^^^ pass this char buffer to the ReadFile function below 

    if (!ReadFile(m_sp_pointer,  // Handle to device 
      buff,     // Receives data from device 
      num,     // num bytes to read (in) 
      (LPDWORD)pNumBytesRead, // num bytes read (out) 
      NULL)) 
     { 
      errcode = GetLastError(); 
     } 

    if (numBytesRead > 0) 
    { 
     return true; 
    } 
    return false; 
} 

Я знаю, что я делаю это не правильно, так что мои вопросы: как я могу сделать это правильно и есть ли что-нибудь, что делает это плохой идеей? Заранее спасибо.

Редактировать: Я действительно должен проходить в unique_ptr в параметрах, а не локально объявлять его и передавать в Message::string& msg.

Моя первоначальная попытка состояла в том, чтобы передать Message::string (std::string) ссылкой, так что это вариант тоже, т. Е. Вместо использования unique_ptr вообще. В , что случае я использовал бы регулярный char[] локально, а затем установить msg содержимое на char[] и вернуть его.

Я не уверен, что было бы лучше, кажется, что несколько ответов рекомендуют vector<char>. (Было бы очень похоже на использование std::string).

+1

Я бы использовал 'std :: vector buff (num);'. – aschepler

ответ

7

Я не думаю, что вам нужно std::unique_ptr. Я предпочел бы std::vector в этом случае:

std::vector<char> buff(num); //and pass buff.data() to function 
           //which accepts char* 

if (!ReadFile(m_sp_pointer,    // Handle to device 
     buff.data(),      // Receives data from device 
     buff.size(), //(CHANGED THIS TOO) //num bytes to read (in) 
     (LPDWORD)pNumBytesRead,   // num bytes read (out) 
     NULL)) 
    { 
     errcode = GetLastError(); 
    } 

Обратите внимание, что std::vector::data() доступен с C++ 11 только. В C++ 03 вместо этого вы можете использовать &buff[0].

+3

Одно из преимуществ, что 'unique_ptr ' заключается в том, что он не излишне инициализирует данные, которые все равно будут перезаписаны. –

+0

@BenjaminLindley Итак, подумав об этом, я думаю, что мой вопрос: что лучше, если я намерен вернуть данные, которые я прочитал из ReadFile, ссылку на вектор или строку или unique_ptr? – nckturner

+2

@Nawaz, в чем причина предпочтения вектора над std :: unique_ptr? – nckturner

5

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

Я предполагаю, что ReadFile использует буфер и не хранит его нигде - так что на самом деле нет аргумента для умного указателя, содержащего эту функцию. Просто passt сырой указатель с

buff.get() 

Далее комментарий:
Это имеет смысл использовать unique_ptr вне ReadFile, потому что он может помочь правильно обрабатывать память. С помощью «ручного управления памятью» вам нужно будет удалить каждый путь, возвращающийся из функций (например, исключений).

+0

+1 для правильного использования необработанных указателей. –

+0

Итак, Даниэль, спасибо за ввод об использовании регулярных указателей локально в функциях. Отличный совет. Тем не менее, мне нужно вернуть эти данные в вызывающую функцию и передать сообщение через некоторое время после этого. Я редактировал свой первоначальный вопрос для решения этой проблемы. В принципе, мне интересно, для этого случая это их предпочтение для std :: unique_ptr или (std :: string/std :: vector )? – nckturner

+0

На самом деле я поддержал ответ от Наваза. Я попытался придумать пример, где вы предпочитаете умный указатель на массив вместо структуры контейнера, но не смог (может быть, кто-то еще?). Единственное, что я знаю, это то, что вы можете конвертировать unique_ptr в shared_ptr, что в некоторых случаях необходимо. – Daniel

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