【发布时间】:2012-03-12 21:42:19
【问题描述】:
我第一次使用 boost::make_shared 创建共享指针指向的对象。主要是因为我们的代码太慢了,单次分配确实有助于提高性能。
在“硬手动方式”修复了一些内存泄漏之后,我决定通过覆盖所有相关类的新运算符来实现一个简单的内存泄漏检测器,仅用于计算在我们的应用程序的特定点上哪些对象仍然存在。我之前已经实现过几次,惊讶地发现我的代码不再检测到任何对象。
我认为我所要做的就是覆盖“placement new”而不是“普通”运算符 new,因为 make_shared 的 boost 网站文档中的以下内容:
"效果:分配适合 T 类型对象的内存和 通过放置 new 表达式 new( pv ) 在其中构造一个对象 T() 或 new( pv ) T( std::forward(args)... )。分配共享 使用 a 的副本来分配内存。如果抛出异常,则没有 效果。”
但是,我的新展示位置也没有被调用。我编写了一个小测试程序来重现该行为:
#include <iostream>
using namespace std;
#include "boost/shared_ptr.hpp"
#include "boost/make_shared.hpp"
class Test
{
public:
Test() { cout << "Test::Test()" << endl; }
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Test new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
cout << "Test non-throwing new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, void* ptr) throw() {
cout << "Test non-throwing placement new" << endl;
return malloc(size);
}
};
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Global new" << endl;
return malloc(size);
}
int main() {
cout << "..." << endl;
boost::shared_ptr<Test> t1(boost::make_shared<Test>());
cout << "..." << endl;
boost::shared_ptr<Test> t2(new Test());
cout << "..." << endl;
return 0;
}
呈现以下输出:
...
Global new
Test::Test()
...
Test new
Test::Test()
Global new
...
我期待在输出的第 3 行出现“Test non-throwing placement new”。你认为行为应该是什么?您是否同意根据 make_shared 的文档,它应该调用我的 Test 类的placement new 运算符?还是我误会了?
当然,我可以在本地复制 boosts 实现并添加对放置 new 运算符的调用。但是,这是否合适,还是会违反放置 new 的预期语义?
提前感谢您的时间和帮助。
【问题讨论】:
-
通过查看 boost 的
,它使用了全局布局 new 运算符 ::new( pv ) T()。这就是为什么没有调用你的类级别放置...通过在 new 之前删除全局限定符 '::',make_shared 实际上会调用你的类级别放置 new 运算符。
标签: c++ boost new-operator make-shared