C++ 声明类型而不提供名称
我已经在调试模式下在gcc上测试了一些代码,但不确定它是否能在其他编译器上正常工作。C++ 声明类型而不提供名称,c++,compiler-optimization,C++,Compiler Optimization,我已经在调试模式下在gcc上测试了一些代码,但不确定它是否能在其他编译器上正常工作。 我的问题是,编译器将如何优化下面的C++代码(MaxAuto宏): 它总是调用一个函数的构造函数和析构函数吗?或者编译器在任何情况下都会优化这段代码并删除一个(ptr)调用,因为它会认为它不会被更多地使用 UPD: 我知道boost和std::auto_ptr。我有自己的内存管理器,它可以控制内存碎片,帮助避免内存泄漏。现在我想“教”我的内存管理器像在boost和stl中那样创建自动内存 UPD2: 下面是我正
我的问题是,编译器将如何优化下面的C++代码(MaxAuto宏): 它总是调用一个函数的构造函数和析构函数吗?或者编译器在任何情况下都会优化这段代码并删除一个(ptr)调用,因为它会认为它不会被更多地使用 UPD:
我知道boost和std::auto_ptr。我有自己的内存管理器,它可以控制内存碎片,帮助避免内存泄漏。现在我想“教”我的内存管理器像在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");
}
输出:
构造函数调用
调用析构函数
构造函数调用
调用析构函数
自动测试1通过
所以它不能像我想的那样正常工作(我没有检查析构函数调用)。但它调用构造函数的次数是我之前说过的两次。
如何将make_auto_ptr更改为自动声明自动ptr?您的假设是正确的。编译器实现(下面@Steve指出的更正)可以自由地优化此代码(假设它可以编译),因为它没有明显的副作用。它无法优化删除,这将改变语义。(尽管它可以将整个功能优化为零。)
但是有更好的方法可以做到这一点——RAII、作用域\u ptr、共享\u ptr、唯一\u ptr等。除非必须使用宏,否则不要使用宏。因为代码格式不正确,所以什么也不会发生<代码>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
}
编译器可能会对其进行优化。然而,即使没有,自动指针增加的安全性也可能超过几纳秒。为了更像C++,您甚至应该将宏声明转换成一个内联函数来完成同样的事情。编译器能够优化外联函数,如宏。为了提高计算效率,请关注您使用的数据结构和算法。在您拥有了最好的数据结构和算法之后,看看下面这样的低级优化
编辑
我又看了一遍代码。我很难想象析构函数会被优化。最好假设它不是。并不是对你的问题的(直接)回答,但请看一看,因为它已经实现了你在这里要做的事情
e、 g
#包括
int main()
{
boost::作用域的ptr a(新字符);
boost::作用域的ptr b(新字符);
}
如您所述,
std::auto_ptr
不将用户提供的删除器作为参数。
然而,
std::unique_ptr
和std/boost::shared_ptr
可以使用删除器。
那么,如何重载操作符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 ) );
}
void*新操作符(大小、应用程序*应用程序){
返回malloc(s);
}
void操作符delete(void*p,Application*app)throw(){
自由基(p);
}
模板
无效删除(常量*p,应用程序*app){
p->~T();
操作员删除((void*)p,app);
}
模板
结构删除器{
应用程序*app;
删除器(应用程序*应用程序):应用程序(应用程序){}
void操作符()(T const*p)const{delete_p(app);}
};
模板
结构自动转换{
T*ptr;
D德尔;
AutoPtr(T*ptr,D const&del):ptr(ptr),del(del){}
~AutoPtr(){del(ptr);}
};
int main(){
应用程序*app=。。。;
自动传输程序p(新建(应用程序)int,删除程序(应用程序));
}
没有语义,因为此代码没有副作用。如果调用了A(),它将始终调用~A()。问题是:它是否总是调用A()?如果是这个问题,答案是否定的。不是我的反对票,但准确地说,实现是自由的,什么都不做。编译器是否将内存分配/空闲视为无操作取决于实现,而大多数编译器并不这么认为,即使只是因为它们希望支持针对不同内存分配器的链接之类的东西,它们本身可能具有可观察的行为。它不应声明a和b。它应该创建一个实例两次(应该只调用一个()两次)。在离开主基地后把它们摧毁。我想你错过了什么。如何是A(A)代码>不等同于A代码>?+1。“ComeauTest.c”,第17行:错误:“a”已在当前范围内声明,使_auto(a);^“ComeauTest.c”,第17行:错误:类“A”make_auto(A);^不存在默认构造函数“ComeauTest.c”,第18行:错误:“b”已在当前范围内声明,使_auto(b);^“ComeauTest.c”,第18行:错误:不存在类“A”make_auto(b)的默认构造函数^@奥利,其实没什么不同
#include <boost/scoped_ptr.hpp>
int main()
{
boost::scoped_ptr<char> a(new char);
boost::scoped_ptr<char> b(new char);
}
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 ) );
}