我在调试模式下测试了gcc上的一些代码,但不确定它是否适用于其他编译器 我的问题是任何编译器如何优化以下c ++代码(make_auto宏):
class A
{
private:
void *ptr;
public:
A(void* _ptr) {ptr = _ptr;}
~A() {free(ptr);}
};
#define make_auto(ptr) A(ptr)
int main ()
{
char *a = (char*)malloc(sizeof(char)),*b = (char*)malloc(sizeof(char));
make_auto(a);
make_auto(b);
return 0;
}
它总是会调用A的构造函数和析构函数吗?或者编译器会在任何情况下优化此代码并删除A(ptr)调用,因为它可以认为它不会被更多地使用。
UPD:
我知道boost和std :: auto_ptr。我有自己的内存管理器控制内存碎片,有助于避免内存泄漏。现在我想“教”我的内存管理器来创建auto_ptrs,就像它在boost和stl中一样。
UPD2:
这是完整的代码,我正在使用并且我认为工作正确:
class AutoPtr
{
private:
void *ptr;
Application *app;
public:
AutoPtr(Application *_app,void *a)
{
printf("constructor called\n");
ptr = a;
app = _app;
}
~AutoPtr()
{
fast_free(app,ptr);
printf("destructor called\n");
}
};
#define make_auto_ptr(app,ptr) AutoPtr(app,ptr)
static void AutoPtrTest1()
{
test_declare_app
char *a = fast_alloc(app,char,20);
char *b = fast_alloc(app,char,11);
{
make_auto_ptr(app,a);
make_auto_ptr(app,b);
}
test_free_app
printf("Autoptrtest1 passed\n");
}
输出:
构造函数调用 析构函数叫 构造函数调用 析构函数叫 Autoptrtest1通过了
所以它不正常,因为我认为(我没有检查析构函数调用)。但它像我之前所说的那样两次调用构造函数。 如何更改make_auto_ptr以自动声明auto-ptrs?
答案 0 :(得分:7)
没有任何事情发生,因为你的代码格式不正确。 A(a);
和A(b);
声明a
和b
。由于a
已经被声明,并且A
在任何情况下都没有默认构造函数,编译器应该发出诊断信息。
如果您解决了这些问题,那么如果您使用的malloc
和free
是标准库的函数,则允许编译器优化这些问题,因为该代码确实没有可观察的一面效果。
优化编译器应该知道malloc
和free
的特殊含义,我不会惊讶地看到它优化了这一点。但无论出于何种原因,我还可以想象编译器不会优化它。它实际上取决于您的编译器及其使用的标志,但标准肯定允许它在这里进行优化。
以下是clang -O2 -emit-llvm -S main1.cpp -o -
输出的代码:
define i32 @main() nounwind {
ret i32 0
}
答案 1 :(得分:4)
你的假设是正确的。 编译器实现(下面由@Steve指出的更正)可以自由地优化这个代码(假设它完全编译),因为它没有可观察到的副作用。
答案 2 :(得分:1)
编译器可能会优化它。然而,即使它没有,自动指针的附加安全性可能会在这里或那里超过几纳秒。要更多C ++ - 就像你甚至应该将宏声明转换为内联函数来完成同样的事情。编译器能够优化内联函数,如宏。为了提高计算效率,请专注于您使用的数据结构和算法。拥有最好的数据结构和算法后,请查看这样的低级优化。
修改强>
我再次查看了代码。我很难想到析构函数会被优化的情况。最好假设它不会。
答案 3 :(得分:0)
它无法优化删除,这将改变语义。 (虽然它可以将整个功能优化为零。)
但是有更好的方法可以做到这一点 - RAII,scoped_ptr,shared_ptr,unique_ptr等。除非必须,否则不要使用宏。
答案 4 :(得分:0)
如你所说,
std::auto_ptr
不会将用户提供的删除操作作为参数
然而,
std::unique_ptr
和std/boost::shared_ptr
可以删除
那么,如何重载operator new
/ delete
并准备自己的
删除,并给上述智能指针删除?
如果不允许这些智能指针,我建议你制作AutoPtr
使用用户提供的删除器,如下所示:
void* operator new( size_t s, Application* app ) {
return malloc( s );
}
void operator delete( void* p, Application* app ) throw() {
free( p );
}
template< class T >
void delete_( T const* p, Application* app ) {
p->~T();
operator delete( (void*) p, app );
}
template< class T >
struct Deleter {
Application *app;
Deleter( Application* app ) : app( app ) {}
void operator()( T const* p ) const { delete_( p, app ); }
};
template< class T, class D = Deleter<T> >
struct AutoPtr {
T *ptr;
D del;
AutoPtr( T* ptr, D const& del ) : ptr( ptr ), del( del ) {}
~AutoPtr() { del( ptr ); }
};
int main() {
Application *app = ...;
AutoPtr<int> p( new( app ) int, Deleter<int>( app ) );
}
答案 5 :(得分:-1)
不是(直接)回答您的问题,但请查看boost::scoped_ptr,因为它已经实现了您在此处尝试的目标。
e.g。
#include <boost/scoped_ptr.hpp>
int main()
{
boost::scoped_ptr<char> a(new char);
boost::scoped_ptr<char> b(new char);
}