【发布时间】:2018-06-16 16:30:57
【问题描述】:
我一直在通过"Link here" 的 isocpp.org 阅读常见问题解答,并注意到std::vector 的警告:
std::vector<int> v;
auto a = &v[0]; // Is undefined behaviour but
auto a = v.data(); // Is safe
来自实际网站:
void g()
{
std::vector<Foo> v;
// ...
f(v.begin(), v.size()); // Error, not guaranteed to be the same as &v[0]
↑↑↑↑↑↑↑↑↑ // Cough, choke, gag; use v.data() instead
}
此外,如果
std::vector或std::array为空,而使用.data()始终是安全的 功能。
我不确定我是否完全理解这一点。 ::data() 返回指向数组开头的指针,&[0] 返回开头的地址。我没有看到这里的区别,我不认为 &[0] 正在取消引用任何东西(即,没有读取元素 0 处的内存)。在调试版本中的 Visual Studio 上,访问下标 [0] 会导致断言失败,但在发布模式下它什么也没说。对于默认构造的向量,两种情况下的地址也是 0。
我也不明白关于::begin() 的评论不能保证与::operator[0] 相同。我假设对于向量,begin() 迭代器、::data() 和 &[0] 中的原始指针都是相同的值。
【问题讨论】:
-
如果它是空的,那么就没有零索引,并且数据数组可能已经或可能没有为向量创建
-
重点是 v[0],即没有括号,是 UB...,因为您明确要求一个不存在的元素。
-
@Andre 所以换句话说,你可以指向一个无效的地址,但不能用 &。
-
@Zebrafish。确切地说,您可以拥有一个地址无效的指针,并且取消引用是 UB,而不是它自己的指针。在 &v[0] 的情况下,您要求的是一个不存在的元素(使用 v[0]),即 UB。然后,您尝试获取它的地址(使用 &),但此时您已经触发了 UB。
-
@MassimilianoJanes [expr.unary.op]/1 仅定义
*在表达式实际指向对象或函数时的行为。因此,取消引用是遗漏的 UB - 至少在核心问题 232 实际解决之前。
标签: c++ arrays c++11 vector undefined-behavior