向量的记忆行为问题
Questions on memorybehavior of vectors
最近我对std::vectors
的内存分配有点困惑
假设我得到了整数的法向量:std::vector<int> intv;
当我push_back
时,一些int
会随着时间的推移而增长。当我离开函数的作用域(即(时,它会被释放,而不需要额外的调用。
太好了。让我们举另一个例子:
struct foo_t{
std::string bar:
unsigned int derp;
}
void hurr(){
std::vector<foo_t> foov;
foo_t foo;
foo.bar = "Sup?";
foo.derp = 1337;
foov.push_back(foo);
}
好的。当我调用hurr()
时,向量被创建,foo_t
实例被创建,实例被填充并推送到向量。所以当我离开函数时,向量会被释放,内容(这里是foo_t
(也会被释放?
下一个例子:
struct foo_t{
std::string bar:
unsigned int derp;
}
std::vector<foo_t> hurr(){
std::vector<foo_t> foov;
foo_t foo;
foo.bar = "Sup?";
foo.derp = 1337;
foov.push_back(foo);
return foov;
}
在我的理解中,向量及其内容存在于堆栈中,堆栈(最终(会被时间覆盖,而我返回的向量及其内容将毫无用处。或者它实际上返回了向量的副本及其内容的副本(如果内容数据类型不是POD,则需要一个copy Constructor(?
显而易见的是:
struct foo_t{
std::string bar:
unsigned int derp;
}
std::vector<foo_t*> hurr(){
std::vector<foo_t*> foov;
foo_t foo = new foo_t;
foo->bar = "Sup?";
foo->derp = 1337;
foov.push_back(foo);
return foov;
}
现在我必须手动迭代向量,删除其内容,然后我可以安全地让向量超出范围,对吧?
此示例:
struct foo_t{
std::string bar;
unsigned int derp;
};
void hurr(){
std::vector<foo_t> foov;
foo_t foo;
foo.bar = "Sup?";
foo.derp = 1337;
foov.push_back(foo);
}
hurv()
完成后,foov
和foo
都被释放。
std::vector<foo_t> hurr(){
std::vector<foo_t> foov;
foo_t foo;
foo.bar = "Sup?";
foo.derp = 1337;
foov.push_back(foo);
return foov;
}
CCD_ 12的结果CCD_。return foov;
可以调用std::vector<foo_t>
的副本生成器,并且它可以自由不进行该副本,请参阅副本省略
无论如何,从C++11,你可以写这个:
struct foo_t{
std::string bar;
unsigned int derp;
// we will copy the string anyway, pass-by-value
foo_t(std::string bar_, unsigned int d_)
: bar(std::move(bar_)), derp(d_) {}
};
std::vector<foo_t> hurr(){
std::vector<foo_t> foov;
// This is better, in place construction, no temporary
foov.emplace_back("Sup?", 1337);
// This require a temporary
foov.push_back(foo_t{"Sup?", 1337});
return foov;
}
对于最后一个例子,是的,您必须手动覆盖向量,删除其内容,然后当您不想再使用hurr()
的结果时,我可以安全地让向量脱离范围,(不在hurr()
中(
foov.push_back(foo);
实际上,您构建了一个foo_v
并将其推回,这实际上创建了一个新的foo_v
,并使用foov
作为参数调用了复制构造函数。如果要避免这种情况,请使用emplace_back
。
return foov;
编译器可以使用返回值优化对此进行优化。以我在coliru上运行的这个短程序为例。请参阅此问题中的其他优秀答案。
std::vector<foo_t*> foov;
/* add elements to foov with new */
现在我必须手动地覆盖向量,删除它的内容,然后我可以安全地让向量脱离范围,对吧?
是的。出于同样的原因
int* a = new int();
当a
死亡时不会delete a;
。
因此,当我离开函数时,向量会被释放内容(这里是一个
foo_t
(也会被释放吗?
是的。如果foo_t
有非平凡的析构函数,它就会被调用。
或者它真的返回了向量的副本contents(如果其不是POD(?
是的,在这种情况下,它会返回一份副本。现代编译器可能会为std::vector
调用复制构造函数,而CCD_26又会为每个元素调用所包含类型的复制构造函数。C++17引入了保证返回值优化(RVO(,因此不会调用向量的复制构造函数。尽管如此,如果您设置了较高的优化级别,现代编译器也可能使用RVO。
现在我必须手动迭代向量,删除其内容然后我可以安全地让向量落在范围之外,对吧?
是的,你是对的。如果您不想手动迭代,请考虑使用智能指针。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- C++遗传,记忆问题
- 我的记忆动态规划算法有什么问题?
- 在使用SFML时,我会得到记忆或出于界限异常,这是什么问题
- 是记忆问题吗?C [代码块] [Windows]
- 有没有方法可以增加数组的记忆?和相关问题
- 我处理这件事的方式有记忆问题吗
- std::向量记忆问题
- 结合和记忆问题
- 我地图上的记忆问题在哪里?
- 向量的记忆行为问题
- 这会导致记忆问题吗?
- 另一个小记忆C++问题
- 简单的记忆问题练习
- 垫子结构和记忆的问题