所以我有一个项目让用户输入一个选项 op ,取决于它将使用的 vector 的类型,即vector<int>
vector<float>
和vector<double>
。
为此,我创建了3个将根据 op 调用的函数,它的工作方式如下:
#include <iostream>
#include <vector>
using namespace std;
typedef vector<int> intv;
typedef vector<float> flov;
typedef vector<double> douv;
intv vectori(int opt, int t);
flov vectorf(int opt, int t);
douv vectord(int opt, int t);
int main(){
int opt;
size_t t;
cout << "Size: \n";
cin >> t;
cout << "Option? \n";
cin >> op;
flov vf;
douv vd;
intv vi;
switch (op){
case 00:
vi.reserve(t);
vi=vectori(0,t);
break;
case 01:
vf.reserve(t);
vf=vectorf(0,t);
break;
case 02:
vd.reserve(t);
vd=vectord(0,t);
break;
}
}
这将是示例vectori函数:
intv vectori(int op, int t)
{
intv v;
v.reserve(t);
// Do stuff
return v;
}
示例vectorf函数是类似的(因此是vectord):
flov vectorf(int op, int t)
{
flov v;
v.reserve(t);
// Do stuff
return v;
}
所以问题是:
答案 0 :(得分:1)
语句向量
vf
的内存开销是多少,考虑到如果不需要,我不会为它保留内存。
(我假设你的意思是flov vf;
声明)。作为一般准则,内存使用量大致为sizeof(the_vector) + sizeof(element_type) * the_vector.capacity()
。对于特定于实现的调试信息,可能会有更多内容,如果你的实现在增加容量的同时执行它太愚蠢,那么可以进行内存分配页面大小的调整....
请注意std::vector
保证连续内存,因此大量意外实现特定浪费内存的可能性大大低于std::map
,其中内存的碎片和每个单独的节点可能用于分配,调试信息等的开销。
一旦函数vectorx结束,变量v会发生什么?返回v并调用它vi会在内存中创建v的副本吗?
使用C ++ 11,您可以预期vi
将直接填充数据vectorf()
名义上返回(由于返回值优化),或者它将被移动构造,这意味着实际上vi
将获得存储向量元素的指针到动态分配内存的所有权。它相对轻量级,并且随着处理元素数量的增加而变慢。
出于这个原因,你不应该在vi
,vf
和vd
之前保留记忆,然后再为它们分配返回的矢量...你最终可能会分配和释放额外的没有使用它的能力。
这整体记忆效率如何?
对于t
的大值,使不必要的变量的开销变得微不足道,所以是的。请考虑上面提到的reserve
问题 - 因为在分配期间您的瞬间内存使用可能会不必要地过度。
所有这一切,如果您最终选择了三种类型的数据之一供该程序在该运行期间使用,您可能最好使用这样的模板和结构:
#include <iostream>
#include <vector>
template <typename T>
void f(int t)
{
std::vector<T> v(t);
... do all your work with v...
}
int main()
{
int opt;
size_t t;
if (std::cout << "Size:\n" &&
std::cin >> t &&
std::cout << "Option? \n" &&
std::cin >> op)
{
switch (op)
{
case 00: f<int>(t); break;
case 01: f<float>(t); break;
case 02: f<double>(t); break;
}
}
else
std::cerr << "unable to read inputs from stdin\n";
}
答案 1 :(得分:1)
语句向量vf的内存成本是多少,考虑到我 如果不需要,则不为它保留记忆。
标准没有指定容器的初始容量,因此您依赖于实施(请参阅Initial capacity of vector in C++)
无论如何,许多实现都会将容量从零开始。
一旦函数vectorx结束,变量v会发生什么?是否 返回v并调用它vi在内存中创建v的副本?
这取决于编译器。最新的编译器将应用Return Value Optimization或使用移动构造函数(请参阅How to "return an object" in C++?和C++ vector, return vs. parameter)。
这整体记忆效率如何?
我认为可以改进。
reserve
答案 2 :(得分:0)
对于内存成本,您需要将其描述为DumbCoder建议的,它是系统特定的。
变量v是过程的本地变量,因此它将在结束时释放。除非编译器有一些优化,否则返回通常会创建一个副本。研究“返回值优化”,这是特定于编译器的。
另一种更好的矢量传递方式是通过引用参数 void funct(std :: vector&amp; vec,...)
答案 3 :(得分:0)
语句
vector vf;
的内存开销是多少,考虑到如果不需要,我不会为它保留内存。
从技术上讲,这取决于标准库的实现。它预先分配一些内存(即以非零capacity()
开头)是在其权利范围内。但我不认为任何实现实际上都是这样 - 如果向量被分配给(就像你正在做的那样)那将是非常浪费的。
如果你想100%确定,请检查标准库的vector::vector()
实现,但我真的希望不涉及动态内存分配。
函数
v
结束后,变量vectorx
会发生什么?返回v
并将其调用vi
会在内存中创建v
的副本吗?
在C ++ 11及更高版本中,答案是否,不会产生额外的副本。向量v
移动到向量vi
(缓冲区所有权已转移)。
在C ++ 03中,可能会发生副本。如果编译器足够聪明,它可能会发现它可以直接在vi
中构造返回的向量,但我担心这可能是一个太大的精神飞跃。当然,检查装配。
这整体记忆效率如何?
是的,不太可能涉及任何未使用的堆内存。并且vector
对象本身可能只占用堆栈上的3个指针大小。
除此之外:DumbCoder在你的代码中指出了一个严重的缺陷 - reserve()
上vi
和类似向量的调用。这些 nothing 可以提供帮助。向量取得v
缓冲区的所有权(在C ++ 11中移动),或者它将知道要分配多少内存(v.size()
),因此不会有不必要的重新分配。 reserve()
只有在您期望多次添加到向量时才会有意义(例如,push_back()
调用的循环),并且不希望在此期间发生不必要的重新分配。