这里有一些代码示例:
struct Data {
};
struct Init {
Data *m_data;
Init() : m_data(new Data) { }
~Init() {
delete m_data;
}
};
class Object {
private:
int m_initType;
Data *m_data;
public:
Object(const Init &init) : m_initType(0), m_data(init.m_data) { }
Object(Init &&init) : m_initType(1), m_data(init.m_data) { init.m_data = nullptr; }
~Object() {
if (m_initType==1) {
delete m_data;
}
}
};
对象可以通过两种方式初始化:
现在,有一个功能:
void somefunction(Object object);
在callInitA和callInitB中调用此函数:
void callInitA() {
Init x;
somefunction(x); // calls the "const Init &" constructor
}
void callInitB() {
somefunction(Init()); // calls the "Init &&" constructor
}
现在,这就是我想要完成的事情:在callInitA的情况下,我想让编译器优化掉生成的临时 Object <的析构函数调用/ strong>(对象经常使用,我希望减少代码大小。)
然而,编译器并没有对其进行优化(使用GCC和clang测试)。
对象的设计是因为它没有任何改变m_initType的函数,所以编译器能够发现如果m_initType在构造时设置为0,那么它赢了& #39; t改变,所以在析构函数中它仍然是0 - &gt;根本不需要调用析构函数,因为它什么都不做。
甚至,m_initType是对象的不必要成员:它只在破坏时需要。
你有任何设计理念如何实现这个目标吗?
更新:我的意思是使用某种c ++构造(辅助类等)。 C ++是一种强大的语言,可能有某种c ++技巧可以做到这一点。
(我的原始问题更复杂,这个简化的一个:对象可以用其他类型的Init结构初始化,但所有对象构造函数归结为得到一个&#34;数据*&#34;不知何故)
答案 0 :(得分:2)
void callInitA() {
Init x;
somefunction(x); // calls the "const Init &" constructor
}
无论x
的内容如何,都无法优化Init
的破坏。这样做会违反语言的设计。
这不仅仅是Init
是否包含资源的问题。与所有对象一样,Init x
将在堆栈上分配以后需要清理的空间,作为析构函数的隐式(不是您自己编写的代码的一部分)。这是不可避免的。
如果x
的目的是成为somefunction
无需重复创建和删除对x
的引用即可调用的对象,您应该像这样处理它:
void callInitA(Init & x) { //Or Init const& x
somefunction(x); // calls the "const Init &" constructor
}
其他几点说明:
std::unique_ptr
内,因为您似乎不需要超出std::unique_ptr
提供的功能。答案 1 :(得分:0)
你的m_initType
实际上区分了两种Object
- 那些拥有记忆的人和那些没有记忆的人。另外,你提到实际上有很多种Object
可以用各种输入进行初始化;所以实际上有各种Object
s。这表明Object
应该更好地成为一些抽象基类。现在,这不会加速任何事情或避免析构函数调用,但它可能会使您的设计更合理。或者Object
可能是std::variant
(C ++ 17中的新内容,您可以阅读它)。
但是,你说临时Object
是“频繁使用”。所以也许你应该采取另一种方式:在你的例子中,假设你有
template <bool Owning> class Object;
然后你将专门针对非拥有案例,只有一个const Init&amp;构造函数和默认销毁,以及拥有案例,只有一个Init&amp;&amp;构造函数(考虑到你提到的两个)和delete
s的析构函数。这意味着对使用Object的代码进行模板化,许多意味着更大的代码大小,以及必须知道传入的Object
种类;但如果能避免这种情况,请检查是否真的让你非常烦恼。
我想减少代码大小
我有点怀疑你这样做。你在为嵌入式系统编写代码吗?在这种情况下,使用大量临时Object
时会有点奇怪。