wei12345645
wei12345645
采纳率0%
2016-07-04 08:09

c++中new是怎么调用构造函数的

c++中new是怎么调用构造函数的 c++中new是怎么调用构造函数的

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

4条回答

  • devmiao devmiao 5年前

    new有三种使用方式:plain new,nothrow new和placement new。

    (1)plain new顾名思义就是普通的new,就是我们惯常使用的new。在C++中是这样定义的:
    void* operator new(std::size_t) throw(std::bad_alloc);
    void operator delete(void *) throw();

    提示:plain new在分配失败的情况下,抛出异常std::bad_alloc而不是返回NULL,因此通过判断返回值是否为NULL是徒劳的。
    (2)nothrow new是不抛出异常的运算符new的形式。nothrow new在失败时,返回NULL。定义如下:
    void * operator new(std::size_t,const std::nothrow_t&) throw();
    void operator delete(void*) throw();
    (3)placement new意即“放置”,这种new允许在一块已经分配成功的内存上重新构造对象或对象数组。placement new不用担心内存分配失败,因为它根本不分配内存,它做的唯一一件事情就是调用对象的构造函数。定义如下:
    void* operator new(size_t,void*);
    void operator delete(void*,void*);

    提示1:palcement new的主要用途就是反复使用一块较大的动态分配的内存来构造不同类型的对象或者他们的数组。

    提示2:placement new构造起来的对象或其数组,要显示的调用他们的析构函数来销毁,千万不要使用delete。

    char* p = new(nothrow) char[100];
    long q1 = new(p) long(100);
    int *q2 = new(p) int[100/sizeof(int)];
    二.实例
    1.plain new/delete.普通的new
    定义如下:
    void *operator new(std::size_t) throw(std::bad_alloc);
    void operator delete(void
    ) throw();
    注:标准C++ plain new失败后抛出标准异常std::bad_alloc而非返回NULL,因此检查返回值是否为NULL判断分配是否成功是徒劳的。
    测试程序:
    复制代码 代码如下:

    #include "stdafx.h"
    #include
    using namespace std;
    char *GetMemory(unsigned long size)
    {
    char *p=new char[size];//分配失败,不是返回NULL
    return p;
    }
    int main()
    {
    try
    {
    char *p=GetMemory(10e11);// 分配失败抛出异常std::bad_alloc
    //...........
    if(!p)//徒劳
    cout<<"failure"<<endl;
    delete [] p;
    }
    catch(const std::bad_alloc &ex)
    {
    cout<<ex.what()<<endl;
    }

    return 0;
    

    }

    2.nothrow new/delete不抛出异常的运算符new的形式,new失败时返回NULL。
    定义如下:
    复制代码 代码如下:

    void operator new(std::size_t,const std::nothrow_t&) throw();
    void operator delete(void
    ) throw();
    struct nothrow_t{}; const nothrow_t nothrow;//nothrow作为new的标志性哑元

    测试程序:
    复制代码 代码如下:

    #include "stdafx.h"
    #include
    #include
    using namespace std;
    char *GetMemory(unsigned long size)
    {
    char *p=new(nothrow) char[size];//分配失败,是返回NULL
    if(NULL==p)
    cout<<"alloc failure!"<<endl;
    return p;
    }
    int main()
    {
    try
    {
    char *p=GetMemory(10e11);
    //...........
    if(p==NULL)
    cout<<"failure"<<endl;
    delete [] p;
    }
    catch(const std::bad_alloc &ex)
    {
    cout<<ex.what()<<endl;
    }

    return 0;
    

    }

    3.placement new/delete 主要用途是:反复使用一块较大的动态分配成功的内存来构造不同类型的对象或者它们的数组。例如可以先申请一个足够大的字符数组,然后当需要时在它上面构造不同类型的对象或数组。placement new不用担心内存分配失败,因为它根本不分配内存,它只是调用对象的构造函数。
    测试程序:
    复制代码 代码如下:

    #include "stdafx.h"
    #include
    #include
    using namespace std;
    class ADT
    {
    int i;
    int j;
    public:
    ADT()
    {
    }
    ~ADT()
    {
    }
    };
    int main()
    {
    char *p=new(nothrow) char[sizeof(ADT)+2];
    if(p==NULL)
    cout<<"failure"< ADT *q=new(p) ADT; //placement new:不必担心失败
    // delete q;//错误!不能在此处调用delete q;
    q->ADT::~ADT();//显示调用析构函数
    delete []p;
    return 0;
    }

    注:使用placement new构造起来的对象或数组,要显式调用它们的析构函数来销毁(析构函数并不释放对象的内存),千万不要使用delete.这是因为placement new构造起来的对象或数组大小并不一定等于原来分配的内存大小,使用delete会造成内存泄漏或者之后释放内存时出现运行时错误。

    点赞 2 评论 复制链接分享
  • devmiao devmiao 5年前

    在C++中使用new来初始化对象的指针成员时必须注意如下事项:
    1. 如果在构造函数中使用new来初始化指针成员,则应在析构函数中使用delete来释放。
    2. new和delete必须相互兼容,new对应与delete、new [ ]对应于delete [ ]。
    3. 如果存在多个构造函数,则必须以相同的方式使用new,要么都用new,要么都用new [ ],因为只有一个析构函数,因此所有的构造函数都必须与它兼容。不过,可以在一个构造函数中用new来初始化指针,而在另外一个构造函数中将指针初始化为空(NULL 或0),只是因为delete (无论是带中括号还是不带中括号)可以用于空指针。
    4. 应定义一个复制构造函数,通过深度复制将一个对象初始化为另一个对象。通常这种构造函数与下面的类似:
    String::String(const String & st)
    {
    len=st..len;
    str=new char [len+1];
    strcpy(str, st.str);
    }
    具体的说就是复制构造函数应分配足够的空间来存储复制的数据,并复制数据,而不是仅仅是数据的地址。
    5. 应当定义一个赋值操作符,并通过深度复制将一个对象复制给另一个对象。通常该方法与下面的类似:
    String & String::operator=( const String & st )
    {
    if( this == &st )
    return *this;
    delete [ ] str ;
    len=st.len;
    str=new char[ len+1 ];
    strcpy( str, st.str );
    return *this;
    }

    点赞 1 评论 复制链接分享
  • John_ToStr John_ToDebug 5年前

    1.首先说一下new为什么调用构造函数:因为每一个类对象都是要占用内存资源的,至少一个字节,如果直接定义一个类对象,那么会根据属性调用
    相应构造函数。但是如果定义一个对象指针,而这个对象指针通过new去为对象动态开辟内存(在这先看看构造函数相关解释:构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。)这就已经表明new开辟完内存之后需要构造函数去初始化其成员。所以必须得调用构造函数。
    2.其次说一下怎么掉的构造函数:其实我觉得你的问题的答案是这样的: 就是一般的函数调用,调不调是由编译器说了算的,如果你能够写一个编译器的话,你也能让他不调用构造,也即是说你可以定义规则,然而目前大家都在微软的软禁下...

    点赞 评论 复制链接分享
  • NK_test NK_test 5年前

    我想你要问的应该是下面这个问题吧:
    如果使用new Node()时调用的是默认构造函数,使用new Node(参数)的话则是自己定义动物构造函数

    点赞 评论 复制链接分享

相关推荐