c++ - 标准库容器和不完整类型的规则是什么?

标签 c++ language-lawyer c++-standard-library incomplete-type

给定一个不完整的类型:

struct S; 
然后,以下声明是:
S *p;            // ok, pointer to incomplete types is allowed

std::deque<S> l;  // error, instantiating std::deque with incomplete type is UB
但是以下声明呢?
std::deque<S> *p;   // seems to be UB like the previous case, 
                   // but is it ok if p is not used till S is defined?

std::deque<S*> p;   // not really sure about this one
编辑:问题使用了std::list而不是std::deque,但这违背了问题的目的,因为std::list明确地是allowed以使用不完整的类型。 std::deque似乎没有这样的permission

最佳答案

std::deque<S> *p;   // seems to be UB like the previous case, 
                   // but is it ok if p is not used till S is defined?

这实际上是有趣的地方。是的,实例化,即不允许使用类型不完整的容器,对此没有任何规定。但是问题在于它是否真的被实例化了。根据核心语言,不一定必须如此。

[temp.inst]

1 Unless a class template specialization has been explicitly instantiated or explicitly specialized, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.


指向类型的指针不需要该类型是完整的。因此,仅靠该声明通常不足以导致类模板的实例化,因此确定此处违反容器的要求可能为时过早。
当然,除非我们采取“类类型的完整性会影响程序的语义”的原则,否则将违反契约(Contract)的行为包括在标准库中。我想一个实现可以在这里实例化。我不知道有任何实现,所以这可能不是欲望的解释。
因此,为了谨慎起见,我也认为此UB也是如此。

std::deque<S*> p;  // not really sure about this one

这可以。不管S是否完整,S*仍然是完整的对象类型。我之所以这样说,是因为它不包含在

[basic.types]

5 A class that has been declared but not defined, an enumeration type in certain contexts ([dcl.enum]), or an array of unknown bound or of incomplete element type, is an incompletely-defined object type. Incompletely-defined object types and cv void are incomplete types ([basic.fundamental]). Objects shall not be defined to have an incomplete type.


仅在尝试在执行解引用或指针算术的表达式中使用此类指针时,才会出现有关S完整性的约束。但是指针类型本身仍然是完整的。因此,这是容器类型的有效模板参数。

关于c++ - 标准库容器和不完整类型的规则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63061188/

相关文章:

c++ - 从 matlab 生成 C++ 代码

c++ - macOS 中/proc 是否有替代方案?

c++ - 模板依赖 false

c++ - 为什么具有不同访问控制的成员的 union 不是标准布局?

c++ - `unique_ptr::operator bool()` 是否为已从 move()d move 的 unique_ptr 定义?

c++ - forward_iterator 模板类有意义吗?

c++ - 使用小于 O(N^2) 的内存在小于 O(j-i) 的 i-j 范围内找到最小值

c++ - 未定义 对 "_ZNSt5__padIcSt11char_traitsIcEE6_S_padERSt8ios_basecPcPKcllb"符号的引用未从 libstdc++.a(libstdc++.so.6) 导出

c++ - 使用自定义的总体分配器来利用std::vector末尾的内存

c++ - Gnu C++ 宏 __cplusplus 是否符合标准?