提升 static_vector 而不是 std::is_trivially_destructible

boost static_vector not std::is_trivially_destructible

根据this example(左例)

#include <array>
#include <boost/container/static_vector.hpp>

struct X {
  int k;
  std::array<int, 4>                      a;
  boost::container::static_vector<int, 4> b;
  ~X() = default;
};

int huh()
{
  std::array<X, 5> x;
  return 0;
}

看起来 boost::container::static_vector<T, N>T 时是微不足道的可破坏的(当 X 被破坏时没有循环 b 发生)。 huh 被优化为 xor eax, eax; ret(即 return 0 而无需遍历数组。

当我改用具有非平凡析构函数的包含类型时(右例)

#include <array>
#include <boost/container/static_vector.hpp>

struct Y {
  ~Y();
};

struct X {
  int k;
  std::array<int, 4> a;
  boost::container::static_vector<Y, 4> b;
  ~X() = default;
};

int huh()
{
  std::array<X, 5> x;
  return 0;
}

发生循环

    add     rbx, 1
    call    Y::~Y() [complete object destructor]
    cmp     rbx, r12
    jne     .L3

到目前为止,我认为这是有道理的。 static_vector 一个普通可破坏的对象所占用的内存可以在恒定时间内释放,而不管实际存储了多少对象。

令我吃惊的是std::is_trivially_destructible<boost::container::static_vector<int, 4> >::value的值是假的。这只是一个不正确的类型特征吗?

boost::container::static_vector<X, N> 派生自 boost::container::vector<X, ...> class,其中有一些已定义的构造函数。即使它的所有主体在发布时都被编译器删除了,class 已经 not 可以轻易破坏:

struct X
{
};

struct Y
{
    ~Y() = default;
};

struct Z
{
    ~Z() {};
};

static_assert(std::is_trivially_destructible<X>::value, ""); // Succeeds
static_assert(std::is_trivially_destructible<Y>::value, ""); // Succeeds
static_assert(std::is_trivially_destructible<Z>::value, ""); // Fails

这就是它不在当前增强实现中的技术原因。 std::is_trivially_destructible<boost::container::static_vector<int, 4> >::value 是否可以有另一种实现方式?是的,这是可能的,但我想它需要 boost::container::static_vector 对普通可破坏类型的专门化。

boost::static_vector 继承自 boost::vectorhttps://github.com/boostorg/container/blob/develop/include/boost/container/static_vector.hpp#L106。由于 boost::~vector() 是非平凡的,因此 boost::vectorboost::static_vector 也是如此。


请注意,您的推理是错误的。在第二种情况下,无法优化析构函数调用,因为编译器看不到它的定义。尝试将 Y(); 更改为 ~Y() { }。一个简单的演示:https://godbolt.org/z/pg2xS4.

如果非平凡的析构函数调用没有可观察到的效果,为什么不允许编译器优化它们?