在c++中声明向量和集合

Declaring vectors and sets in C++

本文关键字:集合 向量 声明 c++      更新时间:2023-10-16

这是我第一次在c++中使用STL容器,当我在Google上看到不同的例子时,我注意到向量和集合的声明方式。

如果你有一个类a,并且你想在vector中存储这样的元素,你可以使用指向a对象的指针(如下所示)。而对于set,则在声明中使用实际对象。我想知道这样做是否有特殊的原因,或者它只是发生在我看到的例子中。

vector<*A> cont1;
set<A> cont2;

在大多数情况下,您将最终使用具有自动存储时间的对象容器而不是指针/智能指针,因为这样的容器将为您处理难看的内存管理。

在大多数情况下,简单的std::vector<A>应该足够了。这些是非常罕见的情况,需要使用std::vector<A*>代替。这种情况的一个例子可能是在使用该容器的元素时需要实现运行时多态性。另一个例子可能是使用指针,由于性能问题,当复制A是昂贵的时可能出现。另一个原因可能是避免对象切片

最好的做法是永远使用对象的容器,除非你有很好的理由使用指针的容器。即使需要保存指针,也可以使用智能指针


相关问题:如何避免内存泄漏时使用指针的矢量动态分配对象在c++ ?
c++:对象向量vs.指向新对象的指针向量?

我不知道这是普遍的做法。

然而,这样做的一个可能原因是,当vector调整大小时,所包含的对象可以在内存中移动。如果被包含的对象将其this指针指向其他对象,则该指针在resize指针之后可能无效。通过自己存储指针和管理内存,您的对象就不会受到这个问题的困扰。

对于set,您将不会观察到相同的行为,因为集合往往被实现为树。注意:我不认为c++标准库对此做任何保证…

如果作者试图在set中利用这一点,那么他们滥用了封装规则。如果没有,那么您提供的两个示例可能是不相关的。在容器中存储指针(或不存储指针)还有许多其他原因,您可以自由选择。

vector是一种简单的容器,可以容纳任何可复制的内容。因此,根据您的需要,您可以在其中放入对象或指向对象的指针。

虽然集合也可以包含指针,但这样做通常没有多大意义。集合是有序容器,这意味着在创建集合时,需要指定比较函数。如果没有指定,则使用默认的比较函数(std::less<>),这取决于要定义operator<的集合中存储的内容。这实际上似乎对指针有效,因为你可以用<比较指针,但它比较的是指针,而不是它们指向的对象,所以集合最终将按照对象在内存中的相对位置排序。

这只是您遇到的例子。你可以在vector中存储任何东西,从对象本身,到指针,到函数指针。您还可以将其他向量存储在一个向量中以定义多维向量:

// define 4x4 vector
vector< vector<int> > vec(4, vector<int>(4));
vec[i][j] = a;     // write
int b = vec[i][j]; // read
vector<A*> cont1;
cont1.push_back( new A( whatever ) );
vector<A> cont2;
cont2.push_back( A( whatever ) );

这取决于您有哪个用例。要存储对象还是指针?

注意,第一个示例需要您手动delete每个对象,而第二个示例将为您处理删除。尽可能使用第二种方法,除非你知道自己在做什么。

这取决于您想要存储的内容。

std::vector<A*> myVector;

…将创建一个vector,用于存储指向a类型的指针。

std::set<A> mySet;

…将创建一个集合来存储a类型的实际实例。

您可以很容易地将实际实例存储在vector中:

std::vector<A> myVector;

或集合中的指针:

std::set<A*> mySet;

集合和向量的真正区别在于集合包含所有唯一的元素,并且其操作的运行时间不同。它们根本不相等!

差异的原因是可以有两个相等的动态分配对象,但存储在不同的位置。如果你这样做:

A a,b;
std::vector<A> myVector;
myVector.push_back(a);
myVector.push_back(b);

则myVector将包含两个元素,但在以下情况下:

A a,b;
std::set<A> mySet;
mySet.insert(a);
mySet.insert(b);

mySet将只包含一个。如果使用指针,就不会出现这种情况。

此外,动态分配用于vector的项的原因(如其他人所指出的)是为了减少插入的开销。

干杯!