在寻找这个问题的解决方案时,我在另一个论坛上找到了这个帖子 ,该论文说该标准要求完全定义STL-Datastructure的所有模板参数。 这意味着生成一个结构,该结构在其自身内部存储其自身类型的元素,从而调用未定义的行为。 但是据我所知,大多数前C ++ 11数据结构(即std::vectorstd::map等)都没有发现。

实际上可能是在STL-Datastructures中使用不完整类型的问题? 或者更确切地说,以下代码可能导致的潜在危险:

#include <stdint.h>
#include <map>

struct Test {
  std::map<uint32_t, Test> m_map1;
};

int main() {
  return 1;
}

或者这是这些问题之一,这些代码可能无法使用某些STL实现编译,但如果它编译,您可以确定它有效吗?

===============>>#1 票数:5 已采纳

简短的回答是:因为标准是这样说的。 更一般地,取决于实现以及每种类型和功能的作用,实例化模板可能需要完整的定义。 该标准的作者要么不想,要么没有时间详细分析和详细说明他们不希望在什么情况下要求完整的定义,并且要求一揽子声明。 还要注意,在编写标准时,对STL的经验相对较少,并且可以确定没有一些聪明的优化需要在类中使用参数类型的实例; 而不是冒着禁止这种优化的风险,要求一个完整的类型似乎更安全。

===============>>#2 票数:1

编译器面对不完整类型的至少一个问题是它可能无法完全确定struct Test的大小。 因此,一些容器如何在内部实例化一个测试

实际上,正如詹姆斯所说,这取决于std :: map模板如何使用第二个类型参数。 只要它不使用实例而是测试指针就应该编译。 但谁可以为所有STL-(或一般来说,容器 - )实现声称这个? 由于STL是编译器套件的一部分,因此一个潜在的危险是降低代码的可移植性。

  ask by LiKao translate from so

未解决问题?本站智能推荐:

2回复

为什么STL中允许未定义的行为?

默认情况下, std::stack的“底层容器”是std::deque 。 因此, std::deque的任何未定义行为都是std::stack未定义行为。 cppreference和其他站点在描述成员函数的行为时“有效地”使用术语。 我认为这意味着它适用于所有意图和目的。 因此,调用t
1回复

const_cast const STL容器,它是未定义的行为吗?

我知道使用const_cast不会引入未定义的行为(即可以安全使用),只要您要const_cast ing的变量最初未定义为const或如果最初定义为const而不是通过其const_cast ed别名对其进行修改。 但是,众所周知,大多数STL容器(例如std::vector , std
3回复

带有GNU STL的GCC 4.8为std :: string构造函数生成错误代码?

所以一点C ++代码: 使用GCC 4.8和VS 2013很好地编译。 从我的C ++知识,代码是好的,有一个局部变量theString被带入范围,然后隐藏theString从函数参数。 在theString构造时,作用域中唯一的theString是传递给std::string构造函
1回复

C ++:使用std :: ignore返回std :: tie的类型

我想知道当某些参数为std::ignore时,C ++ 11标准是否对std::tie返回的std::tuple的类型提出了任何要求。 更具体地说,我可以假设: decltype(std::tie(42, std::ignore))与decltype(std::tie(std::
2回复

std :: map operator [] - 未定义的行为?

我只是坚持以下问题:这是否会导致未定义的行为,为什么? 它编译和运行完美,但它没有任何证据。 它类似于常见的UB示例i = ++i + i++; 因为operator[]确实有副作用但另一方面假设任何评估顺序(从左到右和从右到左)使我进入地图的相同最终状态 PS可能相关: ht
3回复

std :: sort - 传递错误的比较器未定义的行为?

考虑以下代码: 如果lhs == rhs,lambda(lhs,rhs)和lambda(rhs,lhs)都将返回true,这违反了提供严格弱排序的要求。 但是,标准是否明确标记将这样的比较器传递为未定义的行为?
1回复

类型和未定义行为之间的指针转换

在C ++中,如果A和B是不同的类,通常将A*强制转换为B*然后取消引用是未定义的行为,即给定 写是未定义的行为 即使x在两个类中具有相同的类型和偏移量也是如此。 另一方面, char*具有强制转换规则的特殊豁免。 如果您这样编写,是否意味着定义明确?
1回复

stl :: deque的insert(loc,val)-与其他位置在deque末尾的行为不一致?

使用http://www.cppreference.com/wiki/stl/deque/insert作为参考,我将值插入双端队列的某些位置。 例如,如果双端队列A为: 使用指向d的迭代器,我可以: 并且iter仍然指向d。 但是,当iter指向g时,最后一个元素:
2回复

这种编译器优化不一致是否完全由未定义的行为来解释?

几天前,在与几个同事的讨论中,我用C ++编写了一段代码来说明内存访问冲突。 在经过漫长的几乎专门使用带有垃圾回收的语言的漫长咒语之后,我目前正在缓慢地返回C ++的过程,而且我猜我失去了接触感,因为我对我的短程序所表现出的行为感到困惑。 有问题的代码是这样的: 我在设置了-
3回复

是否未定义行为来读取和比较POD类型的填充字节?

今天我遇到了一些大致类似于以下代码段的代码。 valgrind和UndefinedBehaviorSanitizer检测到未初始化数据的读取。 当包含填充字节的对象传递给foo时,上述工具抱怨p[i] != p[0]比较。 例: 从POD类型中读取填充字节并将它们与其他内容进