[英]Vector of object pointers, initialisation
我對C ++還不是很有經驗,所以如果這是基本的東西,請耐心等待。
我有一些類似下面的代碼。 L
是一個抽象類(它有許多純虛函數), A
, B
和C
是從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
。 當我嘗試編譯器抱怨它“在'='標記之前”期望構造函數,析構函數或類型轉換“。 所有類A
, B
和C
都有默認的構造函數。
此外,我的印象是我必須手動delete
使用new
創建的任何內容,但它不會刪除帶有delete
或delete[]
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.