use*_*351 2 c++ operator-overloading new-operator
我在How_To_Find_Memory_Leaks中阅读了有关内存跟踪new和重载的内容delete
我定义了这些全局运算符:
inline void* __cdecl operator new( unsigned int size, const char *file, int line ) {
void* ptr = malloc( size );
AddTrack((DWORD)ptr, size, file, line);
return ptr;
}
inline void* __cdecl operator new( unsigned int size, void* ptr, const char *file, int line ) {
return ptr;
}
Run Code Online (Sandbox Code Playgroud)
它与 new 和 new[] 运算符配合良好,但我在放置 new 时遇到问题(第二个)。我的定义如下:
#define new new( __FILE__, __LINE__)
#define new(x) new( x, __FILE__, __LINE__)
Run Code Online (Sandbox Code Playgroud)
他们分开工作。但是当我尝试使用它们时,会出现错误。据我了解,它们是相互替代的。我知道我可以使用具有可变数量参数的宏,如下所示:
#define new( ... ) new( __VA_ARGS__, __FILE__, __LINE__)
Run Code Online (Sandbox Code Playgroud)
但我需要带有和不带有参数的相同宏,因此new这些行中的两个 -s 都替换为正确的:
g_brushes = new Brush[ num_brushes ];
...
new( &g_brushes[i] )Brush(sides);
Run Code Online (Sandbox Code Playgroud)
如果您决定走上推翻全球新事物的黑暗道路,您必须确保考虑以下所有场景:
\n\nnew Foo; // 1\nnew Foo[10]; // 2\nnew (std::nothrow) Foo; // 3\nnew (p) Foo; // 4 - placement, not overridable\n(Foo*) ::operator new(sizeof(Foo)); // 5 - direct invocation of the operator\nRun Code Online (Sandbox Code Playgroud)\n\n并且应该能够处理除最后一个之外的所有上述问题。不寒而栗。
\n\n必要的技巧和技巧是你的宏应该以 结尾new。当宏以 结尾时new,您可以将调用它的不同方式委托给new自身。
这是一种非线程安全的方法。定义一个类型来捕获调用的上下文,因此我们稍后将能够在运算符本身中检索此上下文,
\n\nstruct new_context {\n new_context(const char* file, const int line)\n : file_(file), line_(line) { scope_ = this; }\n ~new_context() { scope_ = 0; }\n\n static new_context const& scope() { assert(scope_); return *scope_; }\n\n operator bool() const { return false; }\n\n const char* file_;\n const int line_;\nprivate:\n static new_context* scope_;\n};\nRun Code Online (Sandbox Code Playgroud)\n\nnew_context接下来,定义您的覆盖以在调用之前创建一个临时文件,
#define new new_context(__FILE__, __LINE__) ? 0 : new\nRun Code Online (Sandbox Code Playgroud)\n\n在委托给运算符 new 之前使用三元运算符条件赋值来计算表达式,请注意,这是operator bool我们上面定义的 派上用场的地方。
然后在新的覆盖中(我将在这里使用标准 C++98 而不是 MSC C++),您所要做的就是检索上下文:
\n\nvoid* operator new (std::size_t size) throw (std::bad_alloc) {\n std::cout \n << "new" \n << "," << new_context::scope().file_ \n << ":" << new_context::scope().line_ \n << std::endl;\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这种方法将处理上面的所有情况1-4,重要且容易被忽视的是,如果4您的重载未被调用,因为您无法替换新的位置(\xc2\xa718.4.\xe2\ x80\x8b1.3),您仍然知道放置 new 发生了,因为new_context将被创建和销毁。
总而言之,您不需要修改运算符后面的内容new,因此所有可能的语法仍然有效。另一点是,new_context临时对象将一直保持活动状态,直到运算符参与的表达式结束为止,因此您可以安全地从全局单例中获取它。
请参阅现场的 gcc 示例。适应 MSC 留给读者。
\n| 归档时间: |
|
| 查看次数: |
3557 次 |
| 最近记录: |