[英]Is use of std::vector<T*> less safe than std::vector<shared_ptr<T>>?
说我有一个简单的数据类:
struct Foo
{
int iData;
double dData;
};
我可以创建一个可以实现为的容器类:
版本1
struct Bar
{
std::vector<std::shared_ptr<Foo>> fooData;
};
或为:
版本2
struct Bar
{
Bar(){}
Bar(Bar const& copy)
{
for(auto fooPtr: copy.fooData)
{
fooData.push_back(new Foo(*fooPtr));
}
}
~Bar()
{
for(auto fooPtr: fooData)
{
delete fooPtr;
}
}
Bar& operator=(Bar const& rhs)
{
if ( this == &rhs )
{
return *this;
}
for(auto fooPtr: fooData)
{
delete fooPtr;
}
fooPtr.clear(); // Had missed this in the original code.
for(auto fooPtr: rhs.fooData)
{
fooData.push_back(new Foo(*fooPtr));
}
return *this;
}
std::vector<Foo*> fooData;
};
可以肯定的是, 版本1比版本2更容易维护。 但是,我有几个与代码的这一方面正交的问题。
是的,第一种选择更安全。 即,您的副本构造函数有两个内存泄漏源,副本赋值运算符有内存泄漏,这完全是错误的。 此外,默认情况下,第一个选项具有移动分配和移动构造函数,从而提高了性能。 (如果改用std::unique_ptr
则性能会更高)
Bar(Bar const& copy)
{
for(auto fooPtr: copy.fooData)
{
fooData.push_back(new Foo(*fooPtr));
//what happens if `new Foo` throws a bad_alloc?
//or if `Foo(const Foo&)` changes and now throws something?
//or if `fooData.push_back` throws a bad_alloc?
//anything you 'new'd is leaked.
}
}
Bar& operator=(Bar const& rhs)
{
if ( this == &rhs )
return *this;
for(auto fooPtr: fooData)
delete fooPtr;
//You forgot this line:
//fooData.clear();
for(auto fooPtr: rhs.fooData) //sharth notes you wrote copy.fooData but that's obvious
fooData.push_back(new Foo(*fooPtr));
//what happens if `fooData.push_back` throws a bad_alloc?
//the `Foo` you just created is leaked.
return *this;
}
版本1和版本2具有不同的语义。 如果复制Bar对象,则版本1提供对数据的共享访问,而版本2不提供对数据的共享访问。 第2版也有微妙的内存泄漏。 如果new
成功而push_back
失败,则对象泄漏。
为什么不使用更简单的std::vector<Foo>
? 我没有看到在这种情况下使用指针(共享指针或原始指针)的任何理由。 值语义比指针语义容易得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.