我有一个带有原始指针的向量(不,我不能使用智能指针),我想在for循环中将项添加到列表中。我做了一个小试用项目,我想知道这在指针管理方面是否被认为是好的C ++代码。
请仅考虑原始指针管理,我对我试图解决的这个特定问题的智能指针不感兴趣。
一个简单的对象:
class Request
{
public:
std::string name;
};
std::vector<Request*> requests;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = new Request();
req->name = s;
requests.push_back(req);
}
编辑:
所以我想解决的问题是将DOMNode *添加到this库的矢量中。
我开始觉得尝试为我的项目编写一个包含我需要的部件的包装器是一个坏主意。或者图书馆也不好?
我没有使用smart_ptr正常工作,如果有人在那里,那么我想听听它。
答案 0 :(得分:5)
嗯,这会泄漏内存,所以很糟糕。你能用Pointer Container吗?
此代码泄漏的原因是您使用new
在堆上创建对象,但您从不在它们上调用delete
。
至于你评论,如果你有一个手动管理某些资源的对象,你需要The Big Three。
答案 1 :(得分:0)
如果您无法(或允许)使用智能指针,可能您可以使用这样的简单内存管理器:
template <class T>
class MemManager
{
public:
typedef std::vector<T*> Vec;
~MemManager ()
{
size_t sz = v_.size ();
for (size_t i = 0; i < sz; ++i)
delete v_[i];
}
T* pushNewObject ()
{
T* t = NULL;
try
{
t = new T;
if (t != NULL)
v_.push_back(t);
}
catch (std::bad_alloc& ex) { /* handle ex */ }
return t;
}
const Vec& objects() const { return v_; }
private:
Vec v_;
};
// test
{
MemManager<Request> mm;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = mm.pushNewObject();
req->name = s;
}
} // all Request objects will be deleted here when
// the MemManager object goes out of scope.
答案 2 :(得分:0)
我会认为你在方法的最后有一个循环来调用vector
的每个成员上的删除。
仍有问题,特别是异常安全问题。
Request
的创建与vector
中的注册之间发生任何争执,则会丢失内存。一种解决方案是暂时使用scoped_ptr
保留内存push_back
ptr.get()
,然后调用release
方法,因为现在内存归{{1}所有}}。vector
中的项目和销毁它们的点之间抛出任何内容,则需要捕获异常,销毁项目,然后重新抛出。可能还有其他人,但是出于某种原因发明了RAII,没有(正确的......)真的很难做到。
答案 3 :(得分:0)
如果您无法使用智能指针,请使用boost::ptr_vector。
请注意,如果您使用的是TinyXml
,则XmlNode
中的内存管理可能由库决定 - 最近的历史记录iirc是您的许多问题都与正确理解内存所有权和发布范例有关对于这个图书馆。
What memory management do I need to cleanup when using TinyXml for C++?
答案 4 :(得分:-1)
快速改进可能是从RequestVector
派生类std::vector<Request*>
,添加ClearRequests
方法(删除所有Request
个对象并清除向量)和使它成为析构函数ClearRequests
。
(实际上,聚合RequestVector
中的向量可能是更好的选择,但派生类的执行速度更快。)