C++17中std::destroy_at()的用法是什么?

7

我有一个简单的代码片段,其中尝试使用std::destroy_at()释放内存:

#include <iostream>
#include <memory>

using namespace std;

class base
{
public:
  ~base()
  {
    cout << "des" << endl;
  }
};
int main()
{
  {
    base* b1 = new base();
    std::destroy_at(b1); // destructor is executed for b1 object (but memory is not freed for b1)
  }
return 0;
}

有人能指导我如何使用destroy_at()来释放内存吗?原始数据类型也观察到相同的行为。使用最新的VS2017编译器。


4
std::destroy_at 不会释放内存。 - James Picone
1个回答

11

std::destroy_at()并不是用于释放内存的,根据[specialized.destroy]p1,它的作用是调用对象的析构函数:

template<class T>
void destroy_at(T* location);
1. Effects: Equivalent to:

location->~T();

cppreference中给出了一个例子,说明为什么可能需要这样做。在这种情况下,我们已经将新的元素放置到缓冲区中,因此不需要释放内存:

struct Tracer {
    int value;
    ~Tracer() { std::cout << value << " destructed\n"; }
};

int main()
{
    alignas(Tracer) unsigned char buffer[sizeof(Tracer) * 8];

    for (int i = 0; i < 8; ++i)
        new(buffer + sizeof(Tracer) * i) Tracer{i}; //manually construct objects

    auto ptr = std::launder(reinterpret_cast<Tracer*>(buffer));

    for (int i = 0; i < 8; ++i)
        std::destroy_at(ptr + i);
}

这里提出的建议来自扩展内存管理工具,其中提到:
标准库和用户库通常在不使用符合标准的分配器的情况下管理内存。它们可能会使用内部缓冲区(例如 optional),或使用不管理对象生命周期的分配器模型 [bde] [sgi] [eastl] [bitsquid]。这样的替代分配器模型在效率关键应用程序中很常见。

4
考虑到有些类型(尤其是别名类型)很难正确获取伪析构函数的名称,因此这个功能非常必要。 - StoryTeller - Unslander Monica
你还可以指出delete b1是正确的方式,既可以销毁指针所指向的对象,也可以释放指针所指向的存储空间。"你不能使用X来做Y"是很好的,但如果加上"改用Z"会更好。 - Casey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接