为什么以下代码有效?
struct A {
std::vector<A> subAs;
};
A是不完整的类型,对吗?如果有一个A * s的矢量我会理解。但在这里我不明白它是如何工作的。这似乎是一个递归的定义。
答案 0 :(得分:36)
这个paper被采用into C++17,允许在某些STL容器中使用不完整的类型。在此之前,它是未定义的行为。引用文章:
根据对Issaquah会议的讨论,我们实现了 达成共识*采用这种方法 - “不完整的容器 类型“,但将范围限制为
std::vector
,std::list
和std::forward_list
,作为第一步。
至于标准的变化(强调我的):
如果实例化
T
,则可以使用不完整类型vector
allocator 满足 allocator-completeness-requirements (17.6.3.5.1)。 T 应在结果的任何成员之前完成 引用了vector的特化。
所以,如果您在实例化std::allocator<T>
时保留默认std::vector<T, Allocator>
,那么根据论文,它将始终使用不完整类型T
;否则,这取决于您的分配器是否可以使用不完整类型T
进行实例化。
A是不完整的类型,对吗?如果有一个A * s的矢量我会理解。但在这里我不明白它是如何工作的。这似乎是一个递归的定义。
那里没有递归。以极其简化的形式,它类似于:
class A{
A* subAs;
};
从技术上讲,除了size
,capacity
和可能allocator
之外,std::vector
只需要保存指向它管理的A
动态数组的指针它的分配器。 (并且在编译时已知指针的大小。)
因此,实现可能如下所示:
namespace std{
template<typename T, typename Allocator = std::allocator<T>>
class vector{
....
std::size_t m_capacity;
std::size_t m_size;
Allocator m_allocator;
T* m_data;
};
}