2013-08-28 4 views
1

Я пытаюсь удалить все удаление и удаление [] старого приложения и вместо этого использовать интеллектуальные указатели. В следующем фрагменте кода я хочу удалить последнее для cicle.Удалить delete/delete []

std::unique_ptr<MapiFileDesc> fileDesc(new MapiFileDesc[numFiles]); 

for (int i = 0; i < numFiles; ++i) 
{ 
    // Works but I've to delete[] at the end 
    fileDesc[i].lpszPathName = new CHAR[MAX_PATH]; 

    // Does not work. For each iteration the previous array will be deleted 
    // It also happens with shared_array 
    boost::scoped_array<CHAR> pathName(new CHAR[MAX_PATH]); 
    fileDesc[i].lpszPathName = pathName.get(); 
} 

// I want to remove the following cicle 
for (int i = 0; i < numFiles; ++i) 
{ 
    delete [] fileDesc[i].lpszPathName; 
    fileDesc[i].lpszPathName = nullptr; 
} 

Как вы думаете, что это лучший подход к этой ситуации: использовать объект-оболочку, которая будет отслеживать все массивы, созданных и удалять их в деструкторе или использовать вектор повышающего :: shared_array и назначение их к каждому из элементов?

std::vector<boost::shared_array<CHAR> > objs; 

for (int i = 0; i < 10; ++i) 
{ 
    objs.push_back(boost::shared_array<CHAR>(new CHAR[MAX_PATH])); 
} 

мне нужно использовать повышение :: shared_ptr, поскольку я использую VC++ 2008

Спасибо заранее. J. Lacerda

+15

Используйте 'std :: string'. – Fanael

+1

Если вы выделяете 'new []', вам нужно 'std :: unique_ptr '. Но да, вместо этого используйте 'std: string'. – juanchopanza

+0

@juanchopanza Просто для любопытства, это только синтаксис C++ 11, или он будет работать с (старым) 'std :: auto_ptr' должным образом? –

ответ

10
std::vector<std::string > objs(numFiles, std::string(MAX_PATH, 0)); 
std::vector<MapiFileDesc> fileDesc(numFiles); 
for (int i = 0; i < numFiles; ++i) 
    fileDesc[i].lpszPathName=objs[i].data(); 
// after the C API calls, if you do need to use the strings as C++ strings, 
// resync the C++ string length with the C string data 
// (not necessary if you just use them via c_str()) 
for (int i = 0; i < numFiles; ++i) 
    objs[i].resize(strlen(objs[i].c_str()); 

Кстати, если вам не нужно, чтобы передать весь массив API, C, но только одиночными структурами, вы можете сделать один вектор-структуры, которая хранит как MapiFileDesc структуру и std::string, связывание сильно время жизни обоих объектов и позволяет конструктору позаботиться о связи lpszPathName со строкой data(); все же, вероятно, я бы не стал беспокоиться, если эта структура используется только в одной функции.

+0

+1 для ответа, который фактически предоставляет конкретное решение :) – LihO

1
std::unique_ptr<MapiFileDesc[]> fileDesc(new MapiFileDesc[numFiles]); 
typedef std::unique_ptr<CHAR[]> CharBuffer; 
std::vector<CharBuffer> pathNameBuffers; 

for (int i = 0; i < numFiles; ++i) 
{ 
    pathNameBuffers.push_back(CharBuffer(new CHAR[MAX_PATH])); 
    fileDesc[i].lpszPathName = pathNameBuffers.back().get(); 
} 

Это не обнулять указатели в конце, хотя.

+0

Но это освободит выделенную память, когда funtion прекратится, верно? – javlacerda

+0

Да, момент 'pathNameBuffers' выходит за рамки. (Говоря об этом, вы должны объявить это * перед * 'fileDesc', если это возможно, чтобы строки переместили указатели.) –

1

При попытке уменьшить количество указателей/избавиться от уродливого управления памятью уменьшить количество звонков delete и delete[] - это не единственное, что вы можете сделать.

Стандартная библиотека предлагает множество опрятных классов, которые позволят вам работать с объектами с автоматическим хранением. Используйте контейнеры STL, такие как std::vector, вместо массивов в стиле C и для массивов символов, которые семантически представляют строку, используйте соответственно std::string или std::wstring.

0

Мне нравится подход расширенного массива boost. Я думаю, что проблема u r обращается к методу get() в boost shared_array, не увеличивает счетчик ссылок для объекта. Ниже приведена одна работа в вашем примере, которая увеличит счетчик ссылок.

for (int i = 0; i < numFiles; ++i) 
{ 
    // Works but I've to delete[] at the end 
    fileDesc[i].lpszPathName = new CHAR[MAX_PATH]; 

    // Does not work. For each iteration the previous array will be deleted 
    // It also happens with shared_array 
    boost::shared_array<CHAR> pathName(new CHAR[MAX_PATH]); 
    fileDesc[i].lpszPathName = pathName.get(); 

    **// Here is a workaround to increase reference count 
    boost::shared_array<CHAR> pathNameTemp (pathName);** 
} 
+0

После того, как цикл будет превышен, счетчик ссылок будет быть одним, а файлDesc уничтожен, память будет удалена. – ptrehan

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