Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 向量<;X*>;向量vs向量<;X>;*vec_C++_Memory_Memory Management_Vector - Fatal编程技术网

C++ 向量<;X*>;向量vs向量<;X>;*vec

C++ 向量<;X*>;向量vs向量<;X>;*vec,c++,memory,memory-management,vector,C++,Memory,Memory Management,Vector,以下两者在内存使用方面有什么区别: std::vector<X*> vec 标准:向量向量向量 其中每个元素都在堆上,但向量本身不在堆上 及 std::vector*vec 向量在堆上声明,但每个元素(在堆栈上?) 第二个选项没有多大意义——它是否意味着向量指针在堆上,但它指向堆栈上的每个元素 如果你真的这么问: vector<X>* vec = new vector<X>(); vector*vec=newvector(); 这意味着整个向量及其所

以下两者在内存使用方面有什么区别:

std::vector<X*> vec
标准:向量向量向量 其中每个元素都在堆上,但向量本身不在堆上

std::vector*vec
向量在堆上声明,但每个元素(在堆栈上?)


第二个选项没有多大意义——它是否意味着向量指针在堆上,但它指向堆栈上的每个元素

如果你真的这么问:

vector<X>* vec = new vector<X>();
vector*vec=newvector();
这意味着整个向量及其所有元素都在堆上。元素占用堆上的一个连续内存块。

区别在于手动内存管理需要在哪里(以及做什么)

每当C++中有一个原始的C样式指针时,你需要做一些手动内存管理——原始指针可以指向任何东西,编译器不会为你做任何自动的构造或破坏。因此,您需要知道指针指向何处,以及在代码的其余部分中谁“拥有”指向的内存

所以当你有

std::vector<X*> vec;
std::vector<X> *vec;
您确实需要担心向量本身的内存管理,但不需要担心单个元素的内存管理

最简单的是,如果您有:

std::vector<X> vec;
std::向量向量向量机;
然后,您根本不需要担心内存管理——编译器将为您处理它

std::vector<X*> vec

现在这并不是很有用,因为向量将数据存储在堆上,并管理它们携带的内存。所以,只有当你有很好的理由去做的时候才使用它,有时候你会需要它。我没有任何关于它是如何有用的例子。

< P>在使用良好的现代C++风格的代码中,上述任何一个都不是真的。
std::vector
是类型为
X
的对象或其任何子类的句柄集合,您不拥有这些句柄。所有者知道它们是如何分配的,并将解除分配它们——你不知道也不在乎

std::vector*
实际上只能用作函数参数,表示您不拥有(调用方拥有)但要修改的向量。根据一种常见的方法,它是指针而不是向量这一事实意味着它是可选的。更为罕见的是,如果已知附加向量的生命周期比指向它的类的生命周期长,那么它可能会用作类成员

std::vector
X
的各种子类的混合对象的多态集合(也可能是
X
本身)。如果
X
移动成本很高,有时您可能会非多态地使用它,但现代风格使大多数类型移动成本很低


在C++11之前,
std::vector
(是的,右括号之间有一个空格)将用于多态情况和不可复制情况。请注意,
某些智能指针
不是尚未存在的
std::unique\u ptr
,而不是在集合中不可用的
std::auto\u ptr
boost::unique_ptr
是一个不错的选择。在C++11中,集合元素的可复制性要求被放宽为可移动性,因此这个原因完全消失了。(仍然存在一些既不可复制也不可移动的类型,例如ScopeGuard模式,但无论如何都不应将它们存储在集合中)

第二种方法是
vec
是指向
std::vector
的指针,您可以假定这就是它的全部含义。它所指的并不是基于你在这里所拥有的东西而确定的。它可以很容易地指向一个自动向量,就像它可以指向一个动态分配一样(或者完全不确定,现在就是这样)。指针的位置也同样不确定。它可以是动态管理的对象类的成员变量。它可以是一个局部函数变量,也可以是一个全局变量。上下文是一件美好的事情。当你说在
std::vector vec
中元素“在堆上”时,你的确切意思是什么?你的意思是你故意在堆上分配它们?因为本身
std::vector
并不意味着元素“在堆上”。这就是为什么整个“堆”和“堆栈”术语最终不是很有用的原因。@AndreyT我的意思是,向量中包含的指针指向堆上的对象。我假设一个指针总是指向堆?@user997112:指针不会告诉你对象是如何分配的,它只是告诉你在那个位置有一个这种类型的对象;没有任何东西可以阻止您存储指向堆栈分配对象或具有静态存储持续时间的对象的指针(所有这些使用都有合法的用例)。然而,人们通常将堆分配的对象存储在
std::vector
中,这是事实。我想你指的是C++98——没有C++99这样的东西。您应该注意到,上述对流的限制在C++11中是不正确的,因为流是可移动的。但是您的编辑说它们是可复制的,这是错误的。您最初的声明是不可复制的,在C++11和C++1y中仍然正确。@BenVoigt真的吗?我以为它们可以在C++11中复制!你确定吗?@Samer:
ios\u base
copy构造函数被删除。流现在有了移动构造函数,这是Chris所说的,这允许它们被放置在容器中,但仍然不能被复制。它们不是存储在一起的,而是vector保存了指向其元素的指针,甚至
vector-vec
将把元素存储在堆上的一个连续内存块中(容量很小的情况可能例外)。
std::vector<X*> vec
std::vector<std::fstream> vec;
std::vector<std::fstream*> vec;
vec.resize(5);
for(unsigned long i = 0; i < vec.size(); i++)
{
    vec[i] = new std::fstream;
}
vector<int>* vec;
vec = new vector<int>();
vec->resize(5);