我可以使用reinterpret_cast来销毁非动态分配的对象吗?

时间:2016-01-18 16:34:44

标签: c++ reinterpret-cast

我做了一个非常简单的vector实现。我承认我欺骗了很多,唯一的实例变量是例如size_t szT * elem。许多问题中的一个(但这是我所知道的唯一可能导致崩溃的问题)是pop_back()的问题。

template <typename T>
    void vec<T>::pop_back() {
    if (sz == 0)
        return;
    elem[sz-1].~T();
    --sz;
}

向量elem是动态分配的数组,但数组中的对象可能是也可能不是。我在这里可以看到的问题是,如果我销毁此数组中的对象,这可能会崩溃。如果我多次销毁元素,就会发生这种情况。所以说,以防我使用pop_back。对于我的编译器(这看起来很奇怪)似乎没有发生这种情况,但我听说过有人遇到过这个函数的问题。我一直在尝试在网上做一些研究,并找到另一个alternative。这里没有进行零点检查(可能是懒惰),这个例子是使用reinterpret_cast

template<class T>
void Vector<T>::pop_back() {

    // You way want to do a check for empty() before calling the destructor.

    // Call the destructor.
    (reinterpret_cast<T*>(buffer)[_size-1]).~T();

    // It is usual to prefer the pre decrement (and pre increment).
    --_size;
}

问题是,我真的可以使用reinterpret_cast来破坏vector类中非动态分配的对象吗?

修改

根据要求,我将展示我的push_back,我不确定如何正确地编写我可以用于此的短时间跨度。我承认这个类的主要目的不是效率,而是处理资源而不是原始动态数组的好方法(我当然可以使用向量,但这是一个关于范围小于一般策略的问题,所以我很感激,如果删除了use-std :: vector讨论。

template <typename T>
void vec<T>::push_back(const T& obj) {
    T* tmp = new T[sz+1];
    if (sz > 0){
        uninitialized_copy(elem, elem+sz, tmp);
        delete[] elem;
    }
    elem = tmp;
    elem[sz] = T{obj};
    ++sz;
}

主要问题是能力。我意识到容量部分需要大量工作而没有我可以创建新元素。

1 个答案:

答案 0 :(得分:3)

这个答案的灵感来自Herb Sutter的书 Exceptional C ++ 中的堆栈实现(第12项):

如果您使用

初始化vec变量,则可以为T * elem分配内存
elem = static_cast<T*>(sz == 0 ? nullptr : operator new(sizeof(T)*sz));

这将为您提供尚未构建任何对象的内存。

编辑(感谢Cheers和hth。 - Alf):您也可以通过调用a.allocate(sz)来使用分配器代替上述代码。

如果您想向向量添加新元素,可以使用construct [1]。要调用对象的析构函数,可以使用destroy [2]

如果您现在跟踪变量used中向量中分配的元素数量,您可以通过调用destroy(elem+used);来取消分配最后一个

constructdestroy使用placement new和显式析构函数调用。我建议使用这些函数而不是原始放置新闻和析构函数调用。