gpt4 book ai didi

c++ - 全局新运算符重载

转载 作者:搜寻专家 更新时间:2023-10-31 01:05:50 25 4
gpt4 key购买 nike

我在 How_To_Find_Memory_Leaks 中阅读了关于内存跟踪的newdelete 重载|

我定义了这些全局操作符:

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;
}

它适用于 new 和 new[] 运算符,但我在放置 new(第二个)时遇到问题。我的定义看起来像:

#define new new( __FILE__, __LINE__)
#define new(x) new( x, __FILE__, __LINE__)

他们分开工作。但是当我尝试同时使用它们时,会出现错误。据我了解,它们相互替代。我知道我可以使用具有可变数量参数的宏,如下所示:

#define new( ... ) new( __VA_ARGS__, __FILE__, __LINE__)

但我需要相同的宏,无论是否有参数,所以这些行中的 new-s 都替换为 right:

g_brushes = new Brush[ num_brushes ];
...
new( &g_brushes[i] )Brush(sides);

最佳答案

如果你决定走覆盖全局新的黑暗道路,你必须确保你考虑了以下所有场景:

new Foo;                            // 1
new Foo[10]; // 2
new (std::nothrow) Foo; // 3
new (p) Foo; // 4 - placement, not overridable
(Foo*) ::operator new(sizeof(Foo)); // 5 - direct invocation of the operator

并且应该能够处理除最后一个以外的所有上述问题。不寒而栗。

必要的知识和技巧是你的宏应该以 new 结尾。 。当您的宏以 new 结尾时,您可以将调用它的不同方式委托(delegate)给 new本身。

这是一种非线程安全的处理方式。定义一个类型来捕获调用的上下文,这样我们稍后就可以在运算符本身中检索这个上下文,

struct new_context {
new_context(const char* file, const int line)
: file_(file), line_(line) { scope_ = this; }
~new_context() { scope_ = 0; }

static new_context const& scope() { assert(scope_); return *scope_; }

operator bool() const { return false; }

const char* file_;
const int line_;
private:
static new_context* scope_;
};

接下来,定义覆盖以创建 new_context调用之前临时的,

#define new new_context(__FILE__, __LINE__) ? 0 : new

在委托(delegate)给 operator new 之前使用三元运算符条件赋值来评估表达式,注意它是 operator bool 的位置我们在上面定义的内容会派上用场。

然后在你的新覆盖中(我将在这里使用标准 C++98 而不是 MSC C++),你所要做的就是检索上下文:

void* operator new (std::size_t size) throw (std::bad_alloc) {
std::cout
<< "new"
<< "," << new_context::scope().file_
<< ":" << new_context::scope().line_
<< std::endl;
return 0;
}

此方法将处理所有情况 1-4从上面看,重要且容易被忽视的是万一 4在未调用重载的情况下,因为您无法替换新的放置(§18.4. 1.3),您仍然知道发生新放置是因为 new_context将被创建和销毁。


总结一下,你不需要修改new之后的内容运算符,因此所有可能的语法仍然有效。另一点是 new_context临时对象将一直保持事件状态,直到运算符参与的表达式结束,因此您可以安全地从全局单例中获取它。


See a gcc example live 适应 MSC 留给读者。

关于c++ - 全局新运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21973607/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com