这是我第一次在 C++ 中使用 STL 容器,在 Google 中看到不同的示例时,我注意到声明向量和集合的方式有些东西。
如果你有一个类 A 并且你想将这些元素存储在一个向量中,你可以使用一个指向 A 对象的指针(如下所示)。而对于集合,您在声明中使用实际对象。我想知道这样做是否有特殊原因,或者它只是发生在我看到的示例中。
vector<*A> cont1;
set<A> cont2;
在大多数情况下,您最终将使用具有自动存储持续时间的对象容器而不是指针/智能指针,因为这样的容器将为您处理丑陋的内存管理。
std::vector<A>
在大多数情况下,简单就足够了。这些是非常罕见的需要使用的情况std::vector<A*>
。这种情况的一个示例可能是在使用此容器的元素时需要实现运行时多态性。另一个示例可能是使用指针,因为在复制成本高昂时可能会出现性能问题。A
另一个原因可能是避免对象切片。
好的做法是始终使用对象容器,除非您有充分的理由使用指针容器。即使您需要保存指针,也可以使用智能指针。
相关问题:
在 C++ 中使用指向动态分配对象的指针向量时如何避免内存泄漏?
C ++:对象向量与指向新对象的指针向量?
我不知道这是常见的做法。
但是,这样做的一个可能原因是,在vector
调整大小时,包含的对象可以在内存中移动。如果包含的对象将其this
指针指向其他对象,则该指针可能在resize
. 通过自己存储指针和管理内存,您的对象不会因此受到影响。
使用 a set
,您不会观察到相同的行为,因为集合往往被实现为树。但请注意:我不认为 C++ 标准库对此做出任何保证......
如果作者试图利用这一点,set
那么他们就是在滥用封装规则。如果不是,那么您提供的两个示例可能不相关。将指针存储(或不存储)在容器中的原因还有很多,您可以自由选择。
向量是简单的容器,可以容纳任何可复制的东西。因此,根据您的需要,您可以将对象或指向对象的指针放入其中。
虽然集合也可以包含指针,但这样做通常没有多大意义。集合是有序的容器,这意味着当你创建一个集合时,你需要指定一个比较函数。如果您不指定一个,std::less<>
则使用默认比较函数 ( ),这取决于您在要operator<
定义的集合中存储的任何内容。这实际上似乎适用于指针,因为您可以将指针与 进行比较<
,但它比较的是指针而不是它们指向的对象,因此该集合最终将按照内存中对象的相对位置进行排序。
The real difference between sets and vectors is that a set contains all-unique elements, and has different runtimes for its operations. They aren't equivalent at all!
The reason for the difference is that you can have two dynamically-allocated objects that are equal, but stored in different locations. If you do this:
A a,b;
std::vector<A> myVector;
myVector.push_back(a);
myVector.push_back(b);
then myVector will contain two elements, but in the following case:
A a,b;
std::set<A> mySet;
mySet.insert(a);
mySet.insert(b);
mySet will contain only one. This would not be the case had we used pointers.
Additionally, the reason (as others have noted) for dynamically allocating items for use in a vector is to reduce the overhead of an insertion.
Cheers!
这只是您遇到的示例。您可以在向量中存储从对象本身、指针到函数指针的任何内容。您还可以将其他向量存储在向量中以定义多维向量:
// 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;
...将创建一个存储指向 A 类型的指针的向量。
std::set<A> mySet;
...将创建一个存储 A 类型的实际实例的集合。
您可以轻松地将实际实例存储在向量中:
std::vector<A> myVector;
或集合中的指针:
std::set<A*> mySet;