我发现了一些令人惊讶的东西std::vector,我以为我会在这里问到希望得到一些有趣的答案.
下面的代码只是将字符串复制到char矢量中,并以两种方式打印矢量的内容.
#include <vector>
#include <string>
#include <iostream>
int main()
{
std::string s("some string");
std::vector<char> v;
v.reserve(s.size()+1);
// copy using index operator
for (std::size_t i=0; i<=s.size(); ++i)
v[i] = s[i];
std::cout << "&v[0]: " << &v[0] << "\n";
std::cout << "begin/end: " << std::string(v.begin(), v.end()) << "\n";
// copy using push_back
for (std::size_t i=0; i<=s.size(); ++i)
v.push_back(s[i]);
std::cout << "&v[0]: " << &v[0] << "\n";
std::cout << "begin/end: " << std::string(v.begin(), v.end()) << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
构建和运行此产生:
$ g++ main.cpp -o v && ./v
&v[0]: some string
begin/end:
&v[0]: some string
begin/end: some string
Run Code Online (Sandbox Code Playgroud)
我的期望是它会在两种情况下都正确地打印字符串,但是使用索引运算符begin()end()逐字符分配时不会在以后使用和迭代器时打印任何内容.
end()使用时为什么不更新[]?如果这是故意的,那么它的工作原理是什么?
这种行为有合理的解释吗?:)
到目前为止,我只用gcc 4.6.1尝试过这个.
Mat*_* M. 11
未定义行为的典型示例.
您只能被允许通过索引(使用operator[])在0和v.size()-1(包含)之间访问元素.
使用reserve不修改大小,只修改容量.你会使用resize它,它会按预期工作.
在第一种情况下,您有未定义的行为.reserve设置容量,但将大小保留为零.然后,您的循环将写入向量末尾之外的无效位置.使用(无效)指针打印似乎可以工作(虽然不能保证),因为你已经将字符串写入它指向的内存; 使用迭代器范围打印什么都不打印,因为矢量仍然是空的.
第二个循环每次都正确地增加了大小,因此向量实际上包含了预期的内容.
使用[]时为什么不更新end()?如果这是故意的,那么它的工作原理是什么?
[]旨在尽可能快,因此它不进行范围检查.如果要进行范围检查,请使用at(),这将在超出范围的访问中引发异常.如果要调整阵列大小,则必须自己完成.