矢量指针内存分配的矢量
Vector of vector pointer memory allocation
首先我想说,我有一个向量,里面有一千个向量。这些内部向量中的每一个内部都有数千个数字。我想保持内存管理的安全,并尽可能减少内存使用。
我想问一下,如果我有一个类似于下面的代码
int size = 10;
vector<vector<double>>* something = new vector<vector<double>>(size);
vector<double>* insideOfSomething;
for(int i = 0; i < size; i++){
insideOfSomething = &(something->at(i));
//...
//do something with insideOfSomething
//...
}
我知道"某物"会堆积起来。我不明白的是向量放在哪里,"在某物内部"指的是什么?如果它们是在堆栈中创建的,那么这意味着我有一个向量指针,它指向堆中的一个向量,里面有在堆栈中生成的向量?(我现在很困惑。)
如果我有一个类似于下面的代码;
vector<vector<double>*>* something = new vector<vector<double>*>(size);
vector<double>* insideOfSomething;
for(int i = 0; i < size; i++){
something->at(i) = new vector<double>();
insideOfSomething = something->at(i);
//...
//do something with inside insideOfSomething
//...
}
知道吗,我所有的向量都存储在堆中,对吧?
根据内存管理,哪一个更有用?
您应该避免在堆上分配向量,而只在堆栈上声明它们,因为向量将为您管理其在堆上的对象。在任何想避免创建副本的地方,都可以使用引用或const
引用(这是必要的)。
vector<vector<double> > something(size);
for(int i = 0; i < size; i++)
{
vector<double> &insideOfSomething = something.at(i);
//use insideOfSomething
}
让我们对vector进行一个随机、简单的实现,因为我认为这将对您有所帮助。
template <class T, class Alloc>
class vector
{
private:
T* buffer;
std::size_t vector_size;
std::size_t vector_capacity
Alloc alloc;
public:
...
};
在这种情况下,如果我们写:
vector<int> v;
v.push_back(123);
指针buffer
、积分vector_size
和vector_capacity
以及分配器对象alloc
都将在堆栈上创建(同时分配结构填充和对齐所需的任何额外内存)。
然而,向量本身将在堆上分配内存,这个buffer
指针将把它的基地址存储到堆上。它将始终在堆中,并将包含我们所认为的向量的实际内容。
这仍然比这个更有效率:
vector<int>* v = new vector<int>;
v->push_back(123);
...
delete v;
因为这将涉及向量本身(包括其数据成员)的堆分配/释放,以及向量本身为其内部内容(缓冲区)分配的内存。它还引入了一个额外的间接级别。
现在,如果我们有一个向量Somethings
(向量的向量或其他任何东西):
vector<Something> v;
这些Something
实例总是在连续堆缓冲区内分配,因为它们将驻留在向量内部创建和销毁的动态分配的内存块中。
在向量中<>堆中存储的所有数据我认为你应该简单地使用
vector< vector<double> > something;
我想保持内存管理的安全,并尽可能减少内存使用。
然后
vector<vector<double>>* something = new vector<vector<double>>(size);
已经不好了。正如在其他答案中所说,vector
已经在堆上有了它的数据,不需要为了实现这一点而摆弄new
。事实上,物体的位置就像
S t a c k H e a p
(vector<double>) sthng[0]
(vector<vector<double>>) sthng (vector<double>) sthng[1]
...
- - - - - -
(double) sthng[0][0]
(double) sthng[0][1]
...
- - - - - -
(double) sthng[1][0]
(double) sthng[1][1]
...
(当然,堆上的块没有特定的排序)
Joe和hired777的回答解释了无论发生什么,都会在堆上分配一个向量。我将试着对造成这种情况的原因给出一些见解。
向量是一个可调整大小的容器。通常,当它达到容量时,它的大小会翻倍,这意味着它需要能够分配比已经分配的更多的内存。因此,即使在函数内部和堆栈上声明vector,它在内部也会持有指向堆上数据的指针,当超出函数的范围时,它的析构函数会从堆中删除这些数据。
- 通过双指针分配指针
- 在不工作的情况下为数组分配指针,但反过来也可以
- 无法使用"std::make_shared"分配指针
- 分配指针时出现分段错误
- 为什么有时仅使用Ampersand运算符在C 中分配指针
- 重新分配指针阵列的一部分的安全方法
- 为什么在执行增量操作之前分配指针值
- 当指针指向的对象被另一个类的实例删除时,重新分配指针
- 在堆上分配指针的原因是什么?
- 有没有办法防止分配指针?
- 将运算符重写应用于具有动态分配指针的类
- 在堆上分配指针数组
- 在另一个结构中的结构内解除分配指针
- 分配指针后,是否可以为指针指向的事物分配变量名称?
- 重新分配指针后,将类功能与指针一起使用
- 为什么我的新分配指针会自动在程序退出上删除
- 分配指针的方法之间有什么区别?
- 如何声明和分配指针
- 内存分配(指针和堆栈)
- 通过参数分配指针的值