Повышение интеллектуальных указателей и не POD типов (C ++) - PullRequest
0 голосов
/ 29 января 2011

Практикуя со смарт-указателями и видя, как они могут предотвратить утечки памяти и помочь управлению памятью через RAII, я делал следующее:

#include <boost/shared_ptr.hpp>
#include <vector>

#include <iostream>

using std::cout;
using boost::shared_ptr;

class myobj {
    public:
    shared_ptr<int> a;
    myobj() {
        shared_ptr<int> b(new int[50]);
        a = b;
    }
    ~myobj() {}
};

typedef boost::shared_ptr<myobj> myobj_ptr;

int main() {
    for (unsigned int i=0; i < 5000000; i++) {
        myobj *foo = new myobj();
        myobj *bar = new myobj();
        myobj_ptr bar_ptr(bar);

        bar_ptr = myobj_ptr(foo);
        bar = foo;
    }
    return 0;
}

Есть ли способ, которым я мог бы что-то подобноемоя цель встречается в псевдо-коде):

a = new int[50];

Я могу понять, почему это не сработает, из самого файла Boost shared_ptr.hpp, но я не понимаю, почему это не сработаетзатем:

shared_ptr<int> a;
int *b;
myobj() {
    b = new int[50];
    boost::detail::sp_enable_shared_from_this( a, b, b );
}

Это вернуло эту ошибку:

warning: cannot pass objects of non-POD type ‘class boost::shared_ptr<int>’ through ‘...’; call will abort at runtime

Что я не совсем понимаю.

Ответы [ 3 ]

3 голосов
/ 29 января 2011

Во-первых, все, что в boost::detail - это деталь реализации.Не трогайте его, если вы не разрабатываете код, который будет частью самого Boost.

Во-вторых, boost::shared_ptr не может напрямую оборачивать массивы.Это связано с тем, что массивы в C ++ должны быть удалены с помощью delete [], а boost::shared_ptr - с помощью delete.Вместо этого используйте boost::shared_array или, возможно, от boost::shared_ptr до std::vector.Если вам действительно нужно использовать shared_ptr с массивом, вы должны создать его с помощью пользовательского удалителя:

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

// later...
boost::shared_ptr<int> p(new int[50], array_deleter<int>());

Однако на самом деле не делайте этого.Используйте shared_array<int> или shared_ptr<vector<int> >.

Что касается того, почему вы не можете просто сделать:

boost::shared_ptr<int> a;
// later
a = new int;

Это потому, что было бы опасно делать это слишком легко, чтобы сделатьчто-то shared_ptr - помните, если вы сделаете что-то shared_ptr дважды, вы в конечном итоге сделаете это дваждыТаким образом, shared_ptrs будет принимать только сырые указатели через их конструктор.Если вы действительно хотите перезаписать shared_ptr необработанным указателем, вот один из способов:

a.swap(boost::shared_ptr<int>(new int));

Это создает новый указатель, а затем заменяет его на a.Временный умный указатель (со старым значением a) затем освобождается.

2 голосов
/ 29 января 2011

Вы не можете назначить что-то, выделенное с new int[50] для shared_ptr<int>, если только вы не предоставите пользовательское средство удаления, которое выполняет delete[] вместо delete.

enable_shared_from_this предназначен для добавления возможности для типов классов получать собственный разделяемый указатель, вы только что вытащили что-то из пространства имен detail. Это не предназначено для непосредственного использования. Он предназначен для использования следующим образом.

class myobj : public boost::enable_shared_from_this<myobj>
{ //...

Простейшим управляющим контейнером для массивов будет std::vector<int>, а не shared_ptr.

0 голосов
/ 29 января 2011

Для начала вызываемая вами функция находится в пространстве имен detail, что означает, что она, вероятно, не предназначена для непосредственного вызова. Это может иметь какое-то отношение к вашей проблеме.

Что касается конкретной ошибки, которую вы получаете, эта ошибка обычно означает, что вы пытались вызвать функцию varargs, передавая аргумент не POD. В этом случае это потому, что boost::shared_ptr<int> не является типом POD. Я думаю, что это не имеет ничего общего с использованием массивов по сравнению с необработанными указателями; Я думаю, что вы просто вызываете неправильную функцию с неправильными аргументами. Вы хотели использовать boost::shared_from_this?

...