C++ 声明类型而不提供名称

C++ 声明类型而不提供名称,c++,compiler-optimization,C++,Compiler Optimization,我已经在调试模式下在gcc上测试了一些代码,但不确定它是否能在其他编译器上正常工作。 我的问题是,编译器将如何优化下面的C++代码(MaxAuto宏): 它总是调用一个函数的构造函数和析构函数吗?或者编译器在任何情况下都会优化这段代码并删除一个(ptr)调用,因为它会认为它不会被更多地使用 UPD: 我知道boost和std::auto_ptr。我有自己的内存管理器,它可以控制内存碎片,帮助避免内存泄漏。现在我想“教”我的内存管理器像在boost和stl中那样创建自动内存 UPD2: 下面是我正

我已经在调试模式下在gcc上测试了一些代码,但不确定它是否能在其他编译器上正常工作。
我的问题是,编译器将如何优化下面的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 ) );
}