使用 std::vector,为什么 &vec[0] 未定义的行为,而 vec.data() 是安全的?
With std::vector, why is &vec[0] undefined behavior, but vec.data() safe?
我一直在阅读 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
}
此外,
&v[0]
如果std::vector
或std::array
是空的,而使用.data()
始终是安全的 功能。
我不确定我是否完全理解了这一点。::data()
返回指向数组开头的指针,&[0]
返回开头的地址。我在这里没有看到区别,而且我不认为&[0]
正在取消引用任何东西(即,没有读取元素 0 的内存)。在调试版本中的Visual Studio上,访问下标[0]
会导致断言失败,但在发布模式下,它不会说什么。此外,对于默认构造的向量,这两种情况下的地址均为 0。
我也不明白关于::begin()
不能保证与::operator[0]
相同的评论.我假设对于向量,begin()
迭代器中的原始指针、::data()
和&[0]
都是相同的值。
我在这里看不到区别
&v[0]
与&(v[0])
相同,即从v
的第 1 个元素获取地址。但是当v
为空时,根本没有元素,v[0]
只会导致 UB,它试图返回一个不存在的元素;试图从中获取地址是没有意义的。
v.data()
始终是安全的。它将直接返回指向基础数组的指针。当v
为空时,指针仍然有效(它可能为空指针,也可能不是空指针);但请注意,取消引用它(如*v.data()
)也会导致 UB,与v[0]
相同。
我也不明白关于
::begin()
不能保证与::operator[0]
相同的评论
std::vector::begin
将返回一个类型为std::vector::iterator
的迭代器,它必须满足 RandomAccessIterator 的要求。它可能是一个原始指针,但不一定是。将其作为一个类实现是可以接受的。
为了使您的示例更易于理解,您的问题中缺少的信息是void f(Foo* array, unsigned numFoos);
在Foo
向量上调用.begin()
不能保证是一个指针。但是有些实现的行为可能足够像它,使其工作。
在空向量情况下,v.data()
返回一个指针,但您不知道它指向什么。它可能是一个空点,但这不能保证。
这一切都归结为一件简单的事情:您可以向指针添加或减去整数值,但尝试取消引用无效指针是未定义的行为。
比如说,
int a[10];
int* p = a;
int* q = p + 10; // This is fine
int r = *(p + 10) // This is undefined behaviour
在您的示例中:v[0]
与*(v's internal pointer+0)
相同,如果向量为空,这是一个问题。
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 'string.assign(string.data(), 5)' 是明确定义的还是 UB?
- 收到错误"invalid use of non-static data member 'stu::n' "
- C++ 初始化 .data 部分中的变量
- 模式"allocate memory or use existing data"
- boost::asio data owning `ConstBufferSequence`
- Python to C++ Data structure API
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- protobuf C++ SQLite handle blob data
- Omnet++中的.vec和.sca输出有什么区别?
- 错误:字段'dateOfBirth'的类型不完整'Poco::Data::Date'
- vec[i][j] 是否转换为 *(vec + i + j)?
- 为什么构造函数 Message(const T&data) 与 Message(T&& data) 冲突,当 T = int&时?
- "thread-safe data"与"thread-safe code/functions"的区别
- 如何在编译器C++不智能的情况下实现 GLSL vec* 构造语法?
- 如何找到目标文件 *.o 的 ram rom 使用情况(.bss .text .rodata .data)?
- 使用 std::vector,为什么 &vec[0] 未定义的行为,而 vec.data() 是安全的?
- 如果 vec.size() == 0,vec.data() 返回什么
- std::vector: vec.data() or &vec[0]