内存使用量有什么区别:
std::vector<X*> vec
每个元素都在堆上,但向量本身不在
和
std::vector<X>* vec
向量在堆上声明的位置,但每个元素都在(在堆栈上?)。
第二个选项没有多大意义 - 它是否意味着向量指针在堆上,但它指向每个元素,它们在堆栈上?
内存使用量有什么区别:
std::vector<X*> vec
每个元素都在堆上,但向量本身不在
和
std::vector<X>* vec
向量在堆上声明的位置,但每个元素都在(在堆栈上?)。
第二个选项没有多大意义 - 它是否意味着向量指针在堆上,但它指向每个元素,它们在堆栈上?
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);
现在这并不是真的有用,因为向量无论如何都将它们的数据存储在堆上并管理它们携带的内存。所以只有当你有充分的理由这样做时才使用它,有时你会需要它。我没有任何关于它如何有用的例子。
如果这是你真正问的:
vector<X>* vec = new vector<X>();
这意味着整个向量及其所有元素都在堆上。元素在堆上占据一个连续的内存块。
不同之处在于您需要在哪里(以及做什么)进行手动内存管理。
每当你在 C++ 中有一个原始的 C 风格的指针时,你需要做一些手动的内存管理——原始指针可以指向任何东西,编译器不会为你做任何自动构造或销毁。因此,您需要了解指针指向的位置以及谁“拥有”其余代码中指向的内存。
所以当你有
std::vector<X*> vec;
您无需担心向量本身的内存管理(编译器会为您完成),但您确实需要担心X
放置在向量中的指针的指向对象的内存管理。如果您使用 分配它们new
,则需要确保delete
在某些时候手动对其进行分配。
当你有
std::vector<X> *vec;
您确实需要担心向量本身的内存管理,但您不必担心各个元素的内存管理。
最简单的是,如果您有:
std::vector<X> vec;
那么你根本不需要担心内存管理——编译器会为你处理它。
在使用良好的现代 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
is not std::unique_ptr
,它还不存在, not std::auto_ptr
,它在集合中不可用。 boost::unique_ptr
是一个不错的选择。在 C++11 中,集合元素的可复制性要求放宽到可移动性,因此这个原因完全消失了。(还有一些类型既不可复制也不可移动,例如 ScopeGuard 模式,但无论如何这些都不应该存储在集合中)