деструктор на размещение-новый - PullRequest
0 голосов
/ 06 октября 2018

Существует ли шаблон для автоматического вызова деструктора инициализируемого объекта в стеке при выходе из области видимости?Я хочу пропустить необходимость запомнить, чтобы вызвать деструктор явно.Или есть ли другой метод, чем place-new , для создания стекового объекта с хвостом данных переменного размера []?Я использую g ++.

/* g++ f.cpp -o f.exe */
/* 8< --- f.cpp ----  */
#include <stdio.h>
#include <stdlib.h> 
#include <string>
class aclass {
public:
    aclass(int size) : size_(size) {};
    ~aclass() { /* do something */ };
    int size_;
    char data[0];
};

void f(int size)
{
    char v[sizeof(aclass) + size];
    aclass *p = new(static_cast<void*>(&v)) aclass(size);
    p->~aclass();
}

int main(int argc, char **argv)
{
    f(10);
    f(100);
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Уже существует стандартный класс шаблона оболочки, который делает это - std::unique_ptr.

Обратите внимание на предостережения в комментариях

#include <cstdio>
#include <cstdlib> 
#include <string>
#include <memory>

class aclass {
public:
    aclass(int size);
    ~aclass();
    int size_;
    char data[0];   // this is illegal in standard c++
};

// deleter which only calls destructor, does not deallocate
struct inplace_deleter
{
    template<class T>void operator()(T* p) const noexcept
    {
        p->~T();
    }
};

void f(int size)
{
    // VLAs are not standard c++. This is a compiler extension on gcc.
    char v[sizeof(aclass) + size];

    using ptr_type = std::unique_ptr<aclass, inplace_deleter>;
    auto p = ptr_type(new(&v) aclass(size));

    // auto deleted
}

int main()
{
    f(10);
    f(100);
    return 0;
}

https://godbolt.org/z/qEwld-

0 голосов
/ 06 октября 2018

Вы можете создать класс-оболочку следующим образом:

template <typename T>
class Foo {
    private:
        T *m_ptr;
    public:
        Foo(void *area, int size) {
            m_ptr = new(area) T(size);
        }
        Foo(const Foo &) = delete;
        ~Foo() {
            m_ptr->~T();
        }

        void operator=(const Foo &) = delete;

        T *operator->() {
            return m_ptr;
        }
};

Использование:

void f(int size) {
    char v[sizeof(aclass)+size];
    Foo<aclass> p(v, size);

    p->doSomething(); // call a function from aclass
}

Обратите внимание, что вы используете расширение GCC, так как size не является компиляцией-time-константа.

Если бы это была константа времени компиляции, тогда вы могли бы поместить v в Foosize будет параметром шаблона), поэтому f будет проще.

...