根据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
被摧毁时没有发生b
的循环),它看起来像X
是平凡的可破坏的。 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, ...>
类,它有一些定义的构造函数。即使编译器在发布中消除了它的所有主体,该类已经不是简单的可破坏的:
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
这就是为什么它不在当前的boost实现中的技术原因。可以有另一种实施,其中std::is_trivially_destructible<boost::container::static_vector<int, 4> >::value
是真的吗?是的,这是可能的,但我认为它需要boost::container::static_vector
专门化为简单的可破坏类型。
boost::static_vector
继承自boost::vector
:https://github.com/boostorg/container/blob/develop/include/boost/container/static_vector.hpp#L106。由于boost::~vector()
是非平凡的,因此也是boost::vector
和boost::static_vector
。
请注意,你的推理是错误的。在第二种情况下,析构函数调用无法优化,因为编译器没有看到它的定义。尝试将Y();
更改为~Y() { }
。一个简单的演示:https://godbolt.org/z/pg2xS4。
如果没有可观察到的影响,为什么不允许编译器优化掉非平凡的析构函数调用呢?