我一直在尝试使用C ++的向量容器,并注意到当我使用向量的向量并在for循环内创建向量并将其推回时,我仍然能够访问在向量内部创建的这些向量for循环。
我尝试过搜索它,但只遇到了我不太了解的C ++中的移动操作的提法。作为C程序员,当我尝试访问在堆栈中创建的向量时,在以下代码的for循环范围之外,我会遇到分段错误。有人可以在这里向我解释C ++在做什么?这怎么可能?
#include <iostream>
#include <vector>
using namespace std;
void display (const vector<vector<int> >& tdv) {
for (int i = 0; i < tdv.size(); i++) {
for (int j = 0; j <tdv[i].size(); j++) {
cout << " " << tdv[i][j];
}
cout << endl;
}
}
int main () {
vector<vector<int> > vov;
for (int i = 1; i < 5; ++i) {
vector<int> vec(i, i);
vov.push_back(vec);
}
display (vov);
return 0;
}
运行代码时,我得到以下输出:
1
2 2
3 3 3
4 4 4 4
答案 0 :(得分:3)
向量的行为不像引用/指针/迭代器类型。它们不引用别人拥有的对象。他们拥有自己的缓冲区,并且没有该缓冲区的其他所有者,并且在整个生命周期中都使该缓冲区保持活动状态。
向量是一种值类型。创建向量的副本时,您将获得一个包含元素副本的新动态数组。向量的副本与原始缓冲区引用的缓冲区不同。
vector<int> vec(i, i);
这是一个局部变量。该向量在动态内存中分配一个缓冲区。
vov.push_back(vec);
这将在vector的向量缓冲区内创建vector对象的副本。副本具有自己的动态缓冲区。
局部变量在迭代结束时被销毁,但是副本仍然存在于向量的向量中。而且由于每个向量都有自己的唯一缓冲区,因此活动向量的缓冲区不受其他向量被破坏的影响。
答案 1 :(得分:2)
push_back()
将其参数的副本添加到向量中。
vector<int> vec(i, i);
vov.push_back(vec);
这会创建一个临时vec
对象,是的。它将对对象的引用传递给push_back()
方法,该方法将对象的副本添加到向量中(必要时在向量中重新分配所有内容)。
此后,临时对象被销毁,但是没关系。向量中现在存在它的副本。
向量拥有它包含的所有对象。无论使用什么方法向矢量添加内容,对象都会被复制/移动/以任何方式存储到矢量中,并且矢量拥有它。向量就是这样工作的。
当向量被销毁时,向量中的所有对象都随之被破坏。
大多数C ++入门书籍通常都有一些练习特例,以使用类C原语实现类矢量对象。研究这些章节可能会提供参考。
答案 2 :(得分:-1)
向量的空间分配在堆上,而不是在堆栈上。向量构造函数分配空间,向量析构函数释放空间。
这是C ++中的标准。构造函数和析构函数可以为您提供强大的功能。