在我的代码中,我有:
#define EV( event ) SendEvent( new event );
EV( evFormat );
但我想在EV
宏中传递一个创建的对象,例如:
CEvent *ev = new CEvent();
EV( ev );
这可能吗?因为我无法修改EV
宏。
答案 0 :(得分:5)
#define EV( event ) SendEvent( new event ); // Can't be changed.
宏强制每次调用SendEvent
都应该创建一个新的动态对象。你的问题不只是使用宏是愚蠢的,例如降低了源代码的可读性。这也是宏不允许您在调用之前创建对象,并且您不能更改宏;在你的话中“我无法修改EV
宏”。
因此解决方案很简单:
请勿使用该宏,请直接使用SendEvent
,并记住不要delete
。
答案 1 :(得分:4)
当前编写EV
的方式,它将在每次调用时生成一个新对象。但是,该创建不必是与最终传递给SendEvent的类型相同的对象。这是因为预处理器宏和更复杂的表达式的文本性质增加了一些技巧。考虑一下:
class dummy {
private:
static dummy* freeme;
public:
dummy() { freeme = this; }
static bool dofree() { delete freeme; return true; }
};
dummy* dummy::freeme;
CEvent *ev = new CEvent(this);
EV( dummy && dummy::dofree() ? ev : NULL );
这将扩展出来,以便你正在运行的新的不是CEvent,而是一个虚拟类......然后你自由,然后整个表达式评估你的事件:
SendEvent( new dummy && dummy::dofree() ? ev : NULL );
(注意:使用?:不如逗号运算符那么好,所以这里有一个浪费的NULL分支从未实际发生。逗号运算符会很好,但预处理器宏特别处理逗号,这是一个无法使用的情况。使其成为线程安全的,留给读者练习。)
为了让它“更干净”,但仍然用EV
来表达......没有明确提及SendEvent
,你可以制作自己的宏:
#define EV2(event) EV( dummy && dummy::dofree() ? event : NULL )
...或者您可以使用SendEvent,因为它似乎完全符合您的要求。但那里的乐趣在哪里? ;-P
正如@AlfPSteinbach指出的那样,将new
变为无操作的更为深奥但轻量级的方法是使用placement new:
int dummy;
CEvent *ev = new CEvent(this);
EV( (&dummy) int ? ev : NULL );
所以现在你正在扩展到:
SendEvent( new (&dummy) int ? ev : NULL );
你正在执行一个新的,但这次不需要担心释放结果!因为我不完全确定这是否是犹太洁食。在线程案例中,我提出了自己的问题:
Is it well-defined/legal to placement-new multiple times at the same address?
答案 2 :(得分:2)
完全可行而不改变宏。这只是冒险。请注意,您必须delete []
#include <memory>
struct CEvent {};
void SendEvent(CEvent*) {}
#define EV( event ) SendEvent( new event );
int main() {
char *cev = new char[sizeof(CEvent)];
CEvent* ev = (CEvent*)cev;
EV( (ev)CEvent );
ev->~CEvent();
delete [] cev;
}
答案 3 :(得分:1)
如果您无法修改EV
宏,则无法进行修改。你不能创建自己的SendEvent( event );
代替吗?
<强>更新强>
是#undef
原始宏的可能性,并提供自己的定义吗?假设你只想要新的行为,你可以做
#undef EV
#define EV( event ) SendEvent( event );
但现在您需要使用EV( new event )
替换原始类型的通话。
答案 4 :(得分:1)
你可能会泄漏内存,除非SendEvent从内部管理它,比如
void SendEvent(const Event *ev) {
doSendEvent(ev);
delete ev;
}
除此之外,你试过这个吗,它应该可行吗
EV(CEvent)
如果没有,你可以redefine operator new使用CEvent类,这样上面的调用就可以了。
但你的问题真的很不寻常。你确定你在那里走正路吗?