簡體   English   中英

對象指針傳染媒介,初始化

[英]Vector of object pointers, initialisation

我對C ++還不是很有經驗,所以如果這是基本的東西,請耐心等待。

我有一些類似下面的代碼。 L是一個抽象類(它有許多純虛函數), ABC是從L派生的常規類。 可能有這些中的任何一個,它們都是不同的。

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()) {
            // ...
        }
    }

    // ...
}

它有效,但實際上必須有一個更好的方法來初始化該向量。 對?

首次初始化后,矢量不應該改變。 我認為我不能使它成為const,因為各種對象本身可能會發生變化。 我在常規數組上選擇了一個向量,因為我不想手動跟蹤它的長度(這證明容易出錯)。

理想情況下,我想將向量的定義和初始化從main拉出來,最好是一個單獨的文件然后我可以#include 當我嘗試編譯器抱怨它“在'='標記之前”期望構造函數,析構函數或類型轉換“。 所有類ABC都有默認的構造函數。

此外,我的印象是我必須手動delete使用new創建的任何內容,但它不會刪除帶有deletedelete[] ls 如果我嘗試delete ls; 編譯器抱怨“類型'類std :: vector <L *,std :: allocator <L * >>”參數賦予'delete',期望指針“。

以上是否安全或是否會導致一些內存問題?

但實際上必須有一種更好的方法來初始化該向量。 對?

我不這么認為,至少沒有C ++ 0x。 你更喜歡哪種方式? 你的初始化代碼完全正常。

我認為我不能使它成為const,因為各種對象本身可能會發生變化。

你仍然可以使vector本身為const ,只有它的成員類型不能成為const的指針。

我在常規數組上選擇了一個向量,因為我不想手動跟蹤它的長度(這證明容易出錯)。

您不必跟蹤常量數組中的長度:

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];

通常你不需要大小,例如使用Boost.Range。

理想情況下,我想將向量的定義和初始化從main中拉出來,最好是一個單獨的文件然后我可以#include。

這將違反單一定義規則。 您可以將聲明放入頭文件中,但定義必須放入源文件中。

此外,我的印象是我必須手動刪除使用new創建的任何內容,但它不會刪除帶有delete或delete []的ls。

你的印象是正確的,但你沒有用new ,只有它的元素創建ls 使用向量后,您必須delete其每個元素,但不delete向量本身。

支持多態指針的STL容器的推薦替代方法是Boost指針容器庫

您確實必須對您創建的對象使用delete。 您在向量上調用delete而不是對象。 就像是:

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

對於構造問題,您可以將它們包裝到函數中,並將該函數放在它自己的頭文件中。 您還必須確保包含所有相關的類頭文件。

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()};

由於您在編譯時知道大小,我建議使用array而不是vector 使用類模板array而不是C風格數組可以獲得標准容器接口的好處,就像vector 也就是說,您可以在數組上調用size()並獲取迭代器等。

為了確保您不要忘記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>(),
} };

現代編譯器在標准庫中發布了自己的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>(),
} };

請注意,技術上不需要最外面的大括號,但是將它們排除可能會產生編譯器警告,至少這是我編譯器上發生的情況。

理想情況下,我想將向量的定義和初始化從main拉出來,最好是一個單獨的文件然后我可以#include

在這種情況下,您需要一個帶聲明的頭文件和一個定義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