以下内存使用情况有何不同:
std::vector<X*> vec
其中每个元素都在堆上,但向量本身不是
和
std::vector<X>* vec
在堆上声明向量,但每个元素是(在堆栈上?)。
第二个选项没有多大意义 - 它是否意味着向量指针在堆上,但是它指向堆栈上的每个元素?
答案 0 :(得分:3)
std::vector<X*> vec
是类X的指针数组。例如,在C ++ 98中创建不可复制的类/对象数组(例如std :: fstream)时,这很有用。所以
std::vector<std::fstream> vec;
错误,无效。但
std::vector<std::fstream*> vec;
工作,虽然你必须为每个元素创建一个新对象,所以例如,如果你想要5个fstream元素,你必须写一些像
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);
现在这不是很有用,因为矢量无论如何都要将它们的数据存储在堆上并管理它们携带的内存。因此,只有在你有充分的理由这样做时才使用它,有时你会需要它。我没有任何关于它如何有用的例子。
答案 1 :(得分:0)
如果这是你真正的问题:
vector<X>* vec = new vector<X>();
这意味着整个向量及其所有元素都在堆上。这些元素在堆上占用一个连续的内存块。
答案 2 :(得分:0)
区别在于您需要为手动内存管理做什么(以及什么)。
每当你在C ++中有一个原始的C风格指针时,你需要做一些手动内存管理 - 原始指针可以指向任何东西,编译器不会为你做任何自动构建或破坏。所以你需要知道指针指向的位置以及谁拥有&#39;在你的其余代码中指向的内存。
所以当你有
时std::vector<X*> vec;
你不必担心矢量本身的内存管理(编译器会为你做这件事),但你需要担心指向X
对象的内存管理你放在向量中的指针。如果您使用new
分配它们,则需要确保在某些时候手动delete
。
当你有
时std::vector<X> *vec;
你需要担心矢量本身的内存管理,但是你不必担心各个元素的内存管理。
最简单的是,如果你有:
std::vector<X> vec;
然后你根本不需要担心内存管理 - 编译器会为你处理它。
答案 3 :(得分:0)
在使用良好的现代C ++风格的代码中,以上都不是真的。
std::vector<X*>
是类型为X
的对象或其任何子类的句柄的集合,您不拥有它们。所有者知道如何分配它们并将解除分配 - 您不知道并且不关心。
std::vector<X>*
实际上只会被用作一个函数参数,它代表一个你不拥有的向量(调用者所做的),但是你要修改它。根据一种常见的方法,它是指针而不是向量这一事实意味着它是可选的。很少有人可以将它用作类成员,其中已知附加向量的生命周期比指向它的类长。
std::vector<std::unique_ptr<X>>
是X
的各种子类的混合对象的多态集合(直接可能是X
本身)。如果X
移动成本很高,有时你可能会非多态地使用它,但现代风格使得大多数类型移动都很便宜。
在C ++ 11之前,std::vector<some_smart_pointer<X> >
(是的,结束括号之间有空格)将用于多态情况和不可复制的情况。请注意,some_smart_pointer
不是std::unique_ptr
,而不是std::auto_ptr
,而不是boost::unique_ptr
,这在集合中无法使用。 {{1}}是个不错的选择。使用C ++ 11,集合元素的可复制性要求已经放宽到可移动性,因此这个原因完全消失了。 (仍然存在一些既不可复制也不可移动的类型,例如ScopeGuard模式,但这些类型不应存储在集合中)