2012-08-16 4 views
2

Следующий код:станд :: вектор использования станд :: shared_ptr

class Something 
{ 
public: 
    ~Something() 
    { 
    } 
}; 

int main() 
{ 
    Something* s = new Something[1]; // raw pointer received from C api 
    std::shared_ptr<Something> p = std::shared_ptr<Something>(s); 
    std::vector<std::shared_ptr<Something>> v(&p,&p+1); 

    return 0; 
} 

дает следующее сообщение об ошибке в VS Express, 2010:

--------------------------- 
Microsoft Visual C++ Debug Library 
--------------------------- 
Debug Assertion Failed! 

File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp 
Line: 52 

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 

For information on how your program can cause an assertion 
failure, see the Visual C++ documentation on asserts. 

Удалить деструктор от чего-то и ошибка исчезает, Почему я получаю эту ошибку?

Update:

Позже у меня будет что-то вроде:

Something* s = new Something[100]; 

и отдельные разделяемые указатели будут розданы другим объектам

ответ

6
Something* s = new Something[1]; // raw pointer received from C api 
std::shared_ptr<Something> p = std::shared_ptr<Something>(s); 

является неправильное использование, так как

~shared_ptr(); 

Эффекты: - Если * это пустая или доли собственности с другим shared_ptr экземпляра (use_count()> 1), нет никаких побочных эффектов.

- В противном случае, если * этому принадлежит объект p и d, d (p).

- В противном случае * это принадлежит указателю p и вызывается p.

По умолчанию Deleter является operator delete, но у вас есть Something* s = new Something[1];, выделенный массив нового оператора, который должен быть удален с массивами удаления оператора (удаление []), в противном случае это неопределенное поведение. Вы должны построить shared_ptr с конкретным делетером или использовать что-то для массивов, например boost::shared_array.

Например, этот код является правильным.

template<typename T> 
void deleter(T* p) 
{ 
    delete[] p; 
} 

Something* s = new Something[1]; // raw pointer received from C api 
std::shared_ptr<Something> p = std::shared_ptr<Something>(s, deleter<Something>); 
+0

Я мыслил в терминах: что-то * s = новый Something [ 2]; delete s; delete (s + 1); С каждым общим указателем в векторном вызове delete (s + n). Но это, разумеется, неверно. Как может выглядеть судья? s в моем исходном сообщении может указывать на большой массив, а не на массив только 1. – Baz

+0

Что касается делетера, следует ли мне пройти через вектор и проверить счетчик использования и вызвать delete [], когда он достигнет нуля? – Baz

+0

@Baz no, вектор-деструктор автоматически вызывает вызовы деструкторов объектов, которые содержат. – ForEveR

1

Если у вас есть массив C, полный динамически выделенных указателей, использование вектора shared_ptr значительно упрощается:

#include <vector> 
#include <memory> 

struct Foo { }; 

int main() { 

    Foo* foos[5]; // simulate the array of pointers from C API 
    foos[0] = new Foo(); 
    foos[1] = new Foo(); 
    foos[2] = new Foo(); 
    foos[3] = new Foo(); 
    foos[4] = new Foo(); 

    // create vector of shared_ptrs to C pointers 
    std::vector<std::shared_ptr<Foo>> v(foos, foos+5); 

} 
+0

Нет, я действительно получаю указатель на первый элемент в динамически распределенном массиве.Например, массив из 100 Somethings: Something * s = new Something [100]; – Baz

+0

@Baz использование boost :: shared_array в этом случае ... – ForEveR

+0

Пожалуйста, ознакомьтесь с этим вопросом, чтобы понять мою оригинальную проблему: http://stackoverflow.com/questions/11982901/sharing-ownership-over-a-dynamic-array – Baz

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