简体   繁体   English

对传染媒介的尖对指针传染媒介对指针传染媒介的指针

[英]Pointer to vector vs vector of pointers vs pointer to vector of pointers

Just wondering what you think is the best practice regarding vectors in C++. 只是想知道你认为什么是关于C ++中矢量的最佳实践。

If I have a class containing a vector member variable. 如果我有一个包含vector成员变量的类。 When should this vector be declared a: 该向量何时应声明为:

  1. "Whole-object" vector member varaiable containing values, ie vector<MyClass> my_vector; 包含值的“全对象”矢量成员变量,即vector<MyClass> my_vector;
  2. Pointer to a vector, ie vector<MyClass>* my_vector; 指向矢量的指针,即vector<MyClass>* my_vector;
  3. Vector of pointers, ie vector<MyClass*> my_vector; 指针向量,即vector<MyClass*> my_vector;
  4. Pointer to vector of pointers, ie vector<MyClass*>* my_vector; 指针向量的指针,即vector<MyClass*>* my_vector;

I have a specific example in one of my classes where I have currently declared a vector as case 4, ie vector<AnotherClass*>* my_vector; 我在我的一个类中有一个特定的例子,我当前已将一个向量声明为case 4,即vector<AnotherClass*>* my_vector; where AnotherClass is another of the classes I have created. 其中AnotherClass是我创建的另一个类。

Then, in the initialization list of my constructor, I create the vector using new: 然后,在我的构造函数的初始化列表中,我使用new创建向量:

MyClass::MyClass()
: my_vector(new vector<AnotherClass*>())
{}

In my destructor I do the following: 在我的析构函数中,我执行以下操作:

MyClass::~MyClass()
{
  for (int i=my_vector->size(); i>0; i--)
  {
    delete my_vector->at(i-1);
  }
  delete my_vector;
}

The elements of the vectors are added in one of the methods of my class. 向量的元素添加到我的类的一个方法中。 I cannot know how many objects will be added to my vector in advance. 我不知道有多少物体会提前添加到我的矢量中。 That is decided when the code executes, based on parsing an xml-file. 这是在代码执行时决定的,基于解析xml文件。

Is this good practice? 这是好习惯吗? Or should the vector instead be declared as one of the other cases 1, 2 or 3 ? 或者是否应该将向量声明为其他情况1,2或3中的一个?

When to use which case? 何时使用哪种情况?

I know the elements of a vector should be pointers if they are subclasses of another class (polymorphism). 我知道如果向量的元素是另一个类的子类(多态),则它们应该是指针。 But should pointers be used in any other cases ? 但是应该在任何其他情况下使用指针吗?

Thank you very much!! 非常感谢你!!

Usually solution 1 is what you want since it's the simplest in C++: you don't have to take care of managing the memory, C++ does all that for you (for example you wouldn't need to provide any destructor then). 通常解决方案1是您想要的,因为它是C ++中最简单的:您不必管理内存,C ++会为您做所有这些(例如,您不需要提供任何析构函数)。

There are specific cases where this doesn't work (most notably when working with polymorphous objects) but in general this is the only good way. 在某些特定情况下,这不起作用(最明显的是在使用多态对象时),但一般来说这是唯一的好方法。

Even when working with polymorphous objects or when you need heap allocated objects (for whatever reason) raw pointers are almost never a good idea. 即使在处理多态对象或需要堆分配的对象时(无论出于何种原因),原始指针几乎都不是一个好主意。 Instead, use a smart pointer or container of smart pointers. 相反,使用智能指针或智能指针容器。 Modern C++ compilers provide shared_ptr from the upcoming C++ standard. 现代C ++编译器提供了即将推出的C ++标准的shared_ptr If you're using a compiler that doesn't yet have that, you can use the implementation from Boost . 如果您正在使用尚未具有该编译器的编译器,则可以使用Boost中实现

Definitely the first! 绝对是第一个!

You use vector for its automatic memory management. 您使用vector进行自动内存管理。 Using a raw pointer to a vector means you don't get automatic memory management anymore, which does not make sense. 使用指向向量的原始指针意味着您不再进行自动内存管理,这没有意义。

As for the value type: all containers basically assume value-like semantics. 至于值类型:所有容器基本上都假定类似于语义的语义。 Again, you'd have to do memory management when using pointers, and it's vector's purpose to do that for you. 同样,在使用指针时你必须进行内存管理,而向量的目的就是为你做这件事。 This is also described in item 79 from the book C++ Coding Standards . 这也在C ++ Coding Standards一书的第79项中有所描述。 If you need to use shared ownership or "weak" links, use the appropriate smart pointer instead. 如果您需要使用共享所有权或“弱”链接,请改用相应的智能指针。

Deleting all elements in a vector manually is an anti-pattern and violates the RAII idiom in C++. 手动删除向量中的所有元素是一种反模式,违反了C ++中的RAII习语。 So if you have to store pointers to objects in a vector , better use a 'smart pointer' (for example boost::shared_ptr ) to facilitate resource destructions. 因此,如果必须存储指向vector对象的指针,最好使用“智能指针”(例如boost::shared_ptr )来促进资源破坏。 boost::shared_ptr for example calls delete automatically when the last reference to an object is destroyed. 例如, boost::shared_ptr在销毁对象的最后一个引用时自动调用delete

There is also no need to allocate MyClass::my_vector using new . 也没有必要使用new分配MyClass::my_vector A simple solution would be: 一个简单的解决方案是:

class MyClass {

   std::vector<whatever> m_vector;
};

Assuming whatever is a smart pointer type, there is no extra work to be done . 假设whatever是智能指针类型,都没有额外的工作要做 That's it, all resources are automatically destroyed when the lifetime of a MyClass instance ends. 就是这样,当MyClass实例的生命周期结束时,所有资源都会自动销毁。

In many cases you can even use a plain std::vector<MyClass> - that's when the objects in the vector are safe to copy. 在许多情况下,您甚至可以使用普通的std::vector<MyClass> - 即向量中的对象可以安全复制。

In your example, the vector is created when the object is created, and it is destroyed when the object is destroyed. 在您的示例中,向量是在创建对象时创建的,并在对象被销毁时被销毁。 This is exactly the behavior you get when making the vector a normal member of the class. 这正是使vector成为类的普通成员时所获得的行为。

Also, in your current approach, you will run into problems when making copies of your object. 此外,在您当前的方法中,在复制对象时会遇到问题。 By default, a pointer would result in a flat copy, meaning all copies of the object would share the same vector. 默认情况下,指针会产生平面副本,这意味着对象的所有副本将共享相同的向量。 This is the reason why, if you manually manage resources, you usually need The Big Three . 这就是为什么,如果你手动管理资源,你通常需要三巨头

A vector of pointers is useful in cases of polymorphic objects, but there are alternatives you should consider: 指针向量在多态对象的情况下很有用,但您可以考虑使用其他选项:

  1. If the vector owns the objects (that means their lifetime is bounded by that of the vector), you could use a boost::ptr_vector . 如果向量拥有对象(这意味着它们的生命周期受向量的限制),则可以使用boost::ptr_vector
  2. If the objects are not owned by the vector, you could either use a vector of boost::shared_ptr , or a vector of boost::ref . 如果对象不属于向量,则可以使用boost::shared_ptr的向量,或者boost::ref的向量。

A pointer to a vector is very rarely useful - a vector is cheap to construct and destruct. 指向vector的指针很少有用 - vector构造和破坏的成本很低。

For elements in the vector , there's no correct answer. 对于vector元素,没有正确的答案。 How often does the vector change? vector多久变化一次? How much does it cost to copy-construct the elements in the vector ? 复制构造vector的元素需要多少钱? Do other containers have references or pointers to the vector elements? 其他容器是否有vector元素的引用或指针?

As a rule of thumb, I'd go with no pointers until you see or measure that the copying of your classes is expensive. 根据经验,在你看到测量你的课程复制费用昂贵之前,我不会指点。 And of course the case you mentioned, where you store various subclasses of a base class in the vector , will require pointers. 当然,您提到的在vector存储基类的各种子类的情况下,需要指针。

A reference counting smart pointer like boost::shared_ptr will likely be the best choice if your design would otherwise require you to use pointers as vector elements. boost::shared_ptr这样的引用计数智能指针可能是最好的选择,如果你的设计要求你使用指针作为vector元素。

Complex answer : it depends. 复杂的答案:这取决于。

if your vector is shared or has a lifecycle different from the class which embeds it, it might be better to keep it as a pointer. 如果您的向量是共享的,或者具有与嵌入它的类不同的生命周期,那么将它作为指针保留可能会更好。 If the objects you're referencing have no (or have expensive) copy constructors , then it's better to keep a vector of pointer. 如果您引用的对象没有(或者有昂贵的)复制构造函数,那么最好保留指针向量。 In the contrary, if your objects use shallow copy, using vector of objects prevent you from leaking... 相反,如果你的对象使用浅拷贝,使用对象向量可以防止你泄漏......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM