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

标签 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;
}

vector 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,我不确定如何在我可以花在这上面的短时间内正确编写它。我承认该类的主要目的不是效率,而是处理资源而不是原始动态数组的好方法(我当然可以使用 vector ,但这是一个关于范围比一般策略更小的问题,所以我将不胜感激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;
}

主要问题是容量。我意识到容量部分需要大量工作,否则我只能创建新元素。

最佳答案

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

如果使用以下命令初始化 T * elem 变量,则可以为 vec 分配内存

elem = static_cast<T*>(sz == 0 ? nullptr : operator new(sizeof(T)*sz));

这将为您提供尚未构造对象的内存。

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

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

如果您现在跟踪变量 used 中 vector 中分配了多少元素,则可以通过调用 destroy(elem+used); 取消分配最后一个元素>

constructdestroy 使用放置 new 和它们内部的显式析构函数调用。我建议使用这些函数而不是原始放置消息和析构函数调用。

关于c++ - 我可以使用reinterpret_cast来销毁非动态分配的对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34859662/

相关文章:

c++ - 通过 void* 和 reinterpret_cast 从字节字段读取

c++ - 关于复制构造函数和重载赋值运算符

c++ - 如何使用资源获取即初始化来实现构建器模式?

c++ - 在 C++ glib 应用程序中连接到 dbus 信号的最简单方法是什么?

c++ - 为什么 C++ 标准中没有 std::basic_string 类的构造函数,其参数为 std::string_view 类型

c++ - 将无符号解释为有符号

c++ - 使用 const 变量可以避免别名问题吗

c++ - g++-7.0/访问硬件中 constexpr 函数的不同行为

c++ - 将长整数转换为字符数组的最安全方法是什么

c++ - 运行 TrainCascade.exe 时出错