Ale*_*hul 2 c++ destructor vector
我有这个类定义:
class FlashStream
{
public:
explicit FlashStream(const char * url, vector<uint8> * headers, vector<uint8> * data, void * ndata, void * notifyData = NULL, uint32 lastModified = NULL);
~FlashStream();
private:
NPStream _stream;
// ...
}
Run Code Online (Sandbox Code Playgroud)
及其实施:
FlashStream::FlashStream(const char * url, vector<uint8> * headers, vector<uint8> * data, void * ndata, void * notifyData, uint32 lastModified)
{
// ...
memset(&_stream, 0, sizeof(NPStream));
_stream.headers = new char[data->size()];
memcpy((void*)_stream.headers, &(*data)[0], data->size());
// ...
}
FlashStream::~FlashStream()
{
// ...
if(_stream.headers)
delete [] _stream.headers;
_stream.headers = NULL;
// ...
}
Run Code Online (Sandbox Code Playgroud)
现在,当我运行此代码时:
// ...
vector<FlashStream> _streams;
// ...
_streams.push_back(FlashStream(url, headers, data, _npp.ndata, notifyData, lastModified));
// ...
Run Code Online (Sandbox Code Playgroud)
有时候我delete [] _stream.headers;在析构函数中有一个错误,FlashStream当我push_back()去的时候会调用它vector<FlashStream> _streams.
我在SO和其他几个问题上阅读了这个问题,但所有相同的人都不知道如何优雅有效地解决问题.可问题是在拷贝构造函数,但我不知道我怎么能与内存分配,使其成为NPStream.headers和NPStream.url?
析构函数 atpush_back()可以在两种情况下调用。
如前所述,第一种情况发生在将临时对象推入向量时。这不是最好的主意,因为将调用构造函数、复制构造函数和析构函数。您可以将指向对象的指针存储在向量中以避免冗余调用。
C++11 附带的新功能可能会对您有所帮助。
为了避免不必要的复制,请使用std::vector::emplace_back(). 它在向量中就地构造一个对象,而不是复制。
此外,您还可以使用 的移动版本push_back(value_type&& val)。只需在类中定义一个移动构造函数,移动版本push_back()就会自动对临时对象起作用。
第二种情况是达到向量的容量。向量有两个主要值:大小和容量。大小是向量中当前保存的元素数量。容量是向量存储可以容纳的元素数量。因此,当您推回一个元素时,您就增加了向量的大小。如果容量不足以容纳新元素,向量将执行重新分配以增加其容量。在重新分配期间,向量使用复制/移动构造函数重新构造其对象,并使用析构函数删除旧对象。因此,在 处push_back(),向量可以多次调用对象的析构函数。
要降低向量重新调整大小的成本push_back(),请始终使用该std::vector::reserve()方法为对象预分配存储:
std::vector<int> vec;
vec.reserve(20);
for(int i = 0; i<20; ++i)
vec.push_back(i)
Run Code Online (Sandbox Code Playgroud)
此外,您可以通过定义移动构造函数来降低复制对象的成本:
class C
{
public:
C(int c)
: m_c(c)
{
std::cout << "C(int c)" << std::endl;
}
C(C&& c)
: m_c(c.m_c)
{
std::cout << "C(C&& c)" << std::endl;
}
C(const C& c)
: m_c(c.m_c)
{
std::cout << "C(const C& c)" << std::endl;
}
~C()
{
std::cout << "~C()" << std::endl;
}
private:
int m_c;
};
int main()
{
std::vector<C> vc;
for (int i = 0; i < 100; ++i)
vc.push_back(C(i));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果你编译并运行它,你会发现它C(const C& c)根本没有被调用。由于定义了移动构造函数,push_back()因此重新分配将移动您的对象而不是复制它们。
这个说法:
_streams.push_back(FlashStream(url, headers, data, _npp.ndata, notifyData, lastModified));
Run Code Online (Sandbox Code Playgroud)
相当于:
{
FlashStream temp(url, headers, data, _npp.ndata, notifyData, lastModified);
_streams.push_back(temp);
// temp gets destroyed here
}
Run Code Online (Sandbox Code Playgroud)
因此,您创建一个临时的FlashStream对象,该对象被复制到向量中,然后被破坏.您可以通过emplace_back()在C++ 11中使用来避免这种情况:
_streams.emplace_back(url, headers, data, _npp.ndata, notifyData, lastModified);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2516 次 |
| 最近记录: |