简体   繁体   English

对象指针传染媒介,初始化

[英]Vector of object pointers, initialisation

I'm not very experienced with C++ yet, so bear with me if this is basic stuff. 我对C ++还不是很有经验,所以如果这是基本的东西,请耐心等待。

I have some code like that below. 我有一些类似下面的代码。 L is an abstract class (it has a number of pure virtual functions), and A , B and C are regular classes all derived from L . L是一个抽象类(它有许多纯虚函数), ABC是从L派生的常规类。 There may be any number of these, and they are all different. 可能有这些中的任何一个,它们都是不同的。

int main() {
    // ...

    std::vector<L*> ls(3) ; 

    ls[0] = new A ;
    ls[1] = new B ;
    ls[2] = new C ;

    int i ;
    for (i = 0 ; i < ls.size() ; i++) {
        if (ls[i]->h()) {
            // ...
        }
    }

    // ...
}

It works, but there really has to be a better way to initialise that vector. 它有效,但实际上必须有一个更好的方法来初始化该向量。 Right? 对?

The vector is not supposed to change after it has been first initialised. 首次初始化后,矢量不应该改变。 I figure I can't make it const, however, because the various objects may themselves change internally. 我认为我不能使它成为const,因为各种对象本身可能会发生变化。 I picked a vector over a regular array because I don't want to manually keep track of its length (that proved error prone). 我在常规数组上选择了一个向量,因为我不想手动跟踪它的长度(这证明容易出错)。

Ideally I'd like to pull the definition and initialisation of the vector out of main and preferably into a separate file that I can then #include . 理想情况下,我想将向量的定义和初始化从main拉出来,最好是一个单独的文件然后我可以#include When I try that the compiler complains that it "expected constructor, destructor, or type conversion before '=' token". 当我尝试编译器抱怨它“在'='标记之前”期望构造函数,析构函数或类型转换“。 All the classes A , B and C have default constructors. 所有类ABC都有默认的构造函数。

Also, I was under the impression that I have to manually delete anything created using new , but it won't delete ls with either delete or delete[] . 此外,我的印象是我必须手动delete使用new创建的任何内容,但它不会删除带有deletedelete[] ls If I try delete ls; 如果我尝试delete ls; the compiler complains that "type 'class std::vector<L*, std::allocator<L*> >' argument given to 'delete', expected pointer". 编译器抱怨“类型'类std :: vector <L *,std :: allocator <L * >>”参数赋予'delete',期望指针“。

Is the above even safe or does it cause some memory problems? 以上是否安全或是否会导致一些内存问题?

but there really has to be a better way to initialise that vector. 但实际上必须有一种更好的方法来初始化该向量。 Right? 对?

I don't think so, at least not without C++0x. 我不这么认为,至少没有C ++ 0x。 Which way would you prefer? 你更喜欢哪种方式? Your initialization code is completely fine. 你的初始化代码完全正常。

I figure I can't make it const, however, because the various objects may themselves change internally. 我认为我不能使它成为const,因为各种对象本身可能会发生变化。

You can still make the vector itself const , only its member type cannot be a pointer to const then. 你仍然可以使vector本身为const ,只有它的成员类型不能成为const的指针。

I picked a vector over a regular array because I don't want to manually keep track of its length (that proved error prone). 我在常规数组上选择了一个向量,因为我不想手动跟踪它的长度(这证明容易出错)。

You don't have to keep track of the length in constant arrays: 您不必跟踪常量数组中的长度:

L* ls[] = { new A, new B, new C };
// with <boost/range/size.hpp>
std::size_t num = boost::size(ls);
// without Boost, more error-prone
// std::size_t num = sizeof ls / sizeof ls[0];

And often you don't need the size anyway, eg with Boost.Range. 通常你不需要大小,例如使用Boost.Range。

Ideally I'd like to pull the definition and initialisation of the vector out of main and preferably into a separate file that I can then #include. 理想情况下,我想将向量的定义和初始化从main中拉出来,最好是一个单独的文件然后我可以#include。

That would violate the one-definition rule. 这将违反单一定义规则。 You can put the declaration into a header file, but the definition has to go into a source file. 您可以将声明放入头文件中,但定义必须放入源文件中。

Also, I was under the impression that I have to manually delete anything created using new, but it won't delete ls with either delete or delete[]. 此外,我的印象是我必须手动删除使用new创建的任何内容,但它不会删除带有delete或delete []的ls。

Your impression is correct, but you haven't created ls with new , only its elements . 你的印象是正确的,但你没有用new ,只有它的元素创建ls After using the vectors, you have to delete each of its elements, but not the vector itself. 使用向量后,您必须delete其每个元素,但不delete向量本身。

The recommended alternative to STL containers holding polymorphic pointers is the Boost pointer container library . 支持多态指针的STL容器的推荐替代方法是Boost指针容器库

You do indeed have to use delete on the objects you created. 您确实必须对您创建的对象使用delete。 You are calling delete on the vector not the objects. 您在向量上调用delete而不是对象。 Something like: 就像是:

for(size_t i = 0; i < ls.size(); i++){
    delete ls[i];
}

For your construction issue you could wrap them into a function and put that function in it's own header file. 对于构造问题,您可以将它们包装到函数中,并将该函数放在它自己的头文件中。 You would have to make sure to include all of the relevant classes header files as well. 您还必须确保包含所有相关的类头文件。

void init_vector(std::vector<LS*> & v){
    ls[0] = new A ; 
    ls[1] = new B ;
    ls[2] = new C ;
}

如果C ++ 11是可以接受的,那么使用std::array而不是std::vector可能会更好:

std::array<L *, 3> = {new A(), new B(), new C()};

Since you know the size at compile time, I suggest using an array instead of a vector . 由于您在编译时知道大小,我建议使用array而不是vector Using the class template array instead of a C-style array gives you the benefit of a standard container interface, just like a vector . 使用类模板array而不是C风格数组可以获得标准容器接口的好处,就像vector That is, you can call size() on the array and obtain iterators and so on. 也就是说,您可以在数组上调用size()并获取迭代器等。

And to make sure you don't forget to delete the objects, I suggest using smart pointers: 为了确保您不要忘记delete对象,我建议使用智能指针:

#include <boost/array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

boost::array<boost::shared_ptr<L>, 3> ls = { {
    boost::make_shared<A>(),
    boost::make_shared<B>(),
    boost::make_shared<C>(),
} };

Modern compilers ship their own versions of array and shared_ptr in the standard library: 现代编译器在标准库中发布了自己的array版本和shared_ptr

#include <array>
#include <memory>

std::array<std::shared_ptr<L>, 3> ls = { {
    std::make_shared<A>(),
    std::make_shared<B>(),
    std::make_shared<C>(),
} };

Note that the outermost braces are technically not needed, but leaving them out might produce compiler warnings, at least that's what happens on my compiler. 请注意,技术上不需要最外面的大括号,但是将它们排除可能会产生编译器警告,至少这是我编译器上发生的情况。

Ideally I'd like to pull the definition and initialization of the vector out of main and preferably into a separate file that I can then #include 理想情况下,我想将向量的定义和初始化从main拉出来,最好是一个单独的文件然后我可以#include

In that case, you need a header file with a declaration and an implementation file with a definition of ls : 在这种情况下,您需要一个带声明的头文件和一个定义ls的实现文件:

// file ls.h

#ifndef LS_H
#define LS_H

#include <boost/array.hpp>
#include <boost/shared_ptr.hpp>

extern boost::array<boost::shared_ptr<L>, 3> ls;

#endif

// file ls.cpp

#include "ls.h"
#include <boost/make_shared.hpp>

boost::array<boost::shared_ptr<L>, 3> ls = { {
    boost::make_shared<A>(),
    boost::make_shared<B>(),
    boost::make_shared<C>(),
} };

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

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