我对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
创建的任何内容,但不会删除ls
或delete
或{delete[]
1}}。如果我尝试delete ls;
,编译器会抱怨“类型'类std :: vector&lt; L *,std :: allocator&lt; L *&gt;&gt;'参数赋予'delete',期望指针”。
以上是否安全或是否会导致内存问题?
答案 0 :(得分:4)
但是必须有一种更好的方法来初始化该向量。正确?
我不这么认为,至少没有C ++ 0x。你更喜欢哪种方式?你的初始化代码完全正常。
我认为我不能使它成为const,因为各种对象本身可能会在内部发生变化。
你仍然可以使向量本身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创建的任何内容,但不会删除ls,删除或删除[]。
您的展示是正确的,但您尚未使用ls
创建new
,仅创建元素。使用向量后,您必须delete
每个元素,而不是向量本身。
持有多态指针的STL容器的推荐替代方法是Boost pointer container library。
答案 1 :(得分:1)
您确实必须对您创建的对象使用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 ;
}
答案 2 :(得分:0)
如果C ++ 11可以接受,那么使用std::array
代替std::vector
可能会更好:
std::array<L *, 3> = {new A(), new B(), new C()};
答案 3 :(得分:0)
由于你知道编译时的大小,我建议使用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>(),
} };