c++ new运算符是如何调用构造函数的

2023-05-16

文章目录

    • 内存申请和对象构造
    • placement new
    • 答案很简单
    • 参考链接

内存申请和对象构造

       
本文内容简短,只为记录下一次思考过程,事情起源于一句话,“new操作符会调用operator new分配内存再调用构造函数构造对象”,但最近再次看到这句话的时候越看越有疑问,怎么样调用构造函数??于是就带着这个问题顺便看下operator new和placement new的源码加深下印象了。

众所周知构造函数是在实例化一个类对象时调用,通常我们看到的构造函数是下面这样用:

class A{};

int main()
{
    A inst = A();
    A inst2;
    A *p = new A();
}

       
上述几种调用方式,不管是在栈上还是堆上实例化一个类对象时,共同点都是内存的申请和类的构造是绑定在一起的。可以试想一下,既然new是先调用operator new再调用构造函数,那么这个过程如果我们自己手动调用呢:

#include <iostream>
using namespace std;

class A{
public:
    A():a(0){cout<<"A() called!"<<endl;}
    int a;
};

int main()
{
    A *p = (A*)::operator new(sizeof(A));// 直接调用operator new,只分配内存
    p->A();
}

看起来是没什么问题,但实际结果呢?直接编译出错,报错为:

错误:错误地使用了‘A::A’

即使更改为显示调用,仍然无法编译通过:

int main()
{
    A *p = (A*)::operator new(sizeof(A));// 直接调用operator new,只分配内存
    p->A::A();
}

错误:不能直接调用构造函数‘A::A’

到这里就产生了深深的疑问,构造函数不能被显示调用,那new是怎么调用构造函数的?

placement new

另一方面,我们知道placement new就是在已分配内存上构造对象的,那么placement new是如何只调用构造函数的?

class A{
public:
    A():a(0){cout<<"A() called!"<<endl;}
    int a;
};

int main()
{
    char buff[4];
    A *p = new(buff) A;// 在buff上调用构造函数
    p->~A();// placement new需要显式析构
    return 0;
}

答案很简单

先来看下operator new和placement new的实现:

  • operator new:
_GLIBCXX_WEAK_DEFINITION void *
    operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
    {
      void *p;

      /* malloc (0) is unpredictable; avoid it.  */
      if (sz == 0)
        sz = 1;
      p = (void *) malloc (sz);
      while (p == 0)
        {
          new_handler handler = std::get_new_handler ();
          if (! handler)
            _GLIBCXX_THROW_OR_ABORT(bad_alloc());
          handler ();
          p = (void *) malloc (sz);
        }

      return p;
    }
  • placement new:
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT{ return __p; }
inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT{ return __p; }
// Default placement versions of operator delete.
inline void operator delete  (void*, void*) _GLIBCXX_USE_NOEXCEPT { }
inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { } 

       
可以看到,operator new只是对malloc的一些封装,而placement new则是什么都没做只是把指针返回。至此也基本可以猜到答案了,答案就是编译器自动调用的,想一下也必然是这样,new是个运算符不是函数,运算符是一种告诉编译器执行特定的数学或者逻辑操作的符号,又何来定义之说。

下面是一些参考:
Thus, for a class type T, a new-expression such as:

pt = new T;

translates more-or-less into something like:

pt = static_cast(operator new(sizeof(T)));
pt->T();

The first statement acquires storage for a T object by calling operator new, and converts the address of that storage from type void * to type T *. The second initializes the storage by applying T’s default constructor. As I mentioned earlier, a C++ compiler won’t let you write this explicit constructor call, but it’s happy to do it for you.

参考链接

[1] Calling Constructors with Placement New -Dr.Dobb’s
[2] When is the constructor called by ‘new’ operator in C++
[3] 源码
[4] 源码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++ new运算符是如何调用构造函数的 的相关文章

  • new与delete正确用法

    说明 xff1a 推荐使用如下宏 xff0c 可以在一定程度上避免使用空指针 xff0c 野指针的问题 define HW NEW var classname do try var 61 new classname catch var 61
  • Cpp--重载全局的new和delete

    include lt iostream gt include lt process h gt include lt string h gt include lt stdio h gt define MAX SIZE 30000 char M
  • 浅谈重载new操作符

    new是C 43 43 里非常重要的一个关键词 xff0c 用于申请内存 初始化对象 俗话说 有借有还再借不难 xff0c 通过new向操作系统 借 到的内存用完后必然要 还 回去 xff0c 所以对应地还有一个delete操作符与new共
  • c++ 中的重载全局new,delete

    最近做一个小项目 xff0c 对c 43 43 又有很多新的理解 实在不的不让人发出感叹 xff0c c 43 43 太强大了 xff0c 绝对不是一朝一夕就可以领悟她的内涵的 首先我们要清楚 xff0c 为什么我们要重载new xff0c
  • delete释放new[] 以及 delete[]释放new 的问题

    在同花顺 的笔试过程中遇到这么一个类似问题 A ptr 61 new A 10 for int i 61 0 i lt n i 43 43 delete amp ptr i 由此衍生出两个问题 new 申请的空间用delete释放会发生什么
  • 重载new/delete运算符

    下面介绍用重载new delete运算符的方式来实现一个简单的内存泄露检测工具 xff0c 基本思想是重载全局new delete运算符 xff0c 被检测代码调用new和delete运算符时就会调用重载过的operator new和ope
  • 2023 New Year‘s Resolution

    This Is Game 2023 New Year 39 s Resolution My 2022 ended with a day of game I am convinced that I am not to blame becaus
  • set_new_handler(0)

    STL源码剖析 第45页中有一行代码set new handler 0 xff09 xff1a inline T allocate ptrdiff t size T std set new handler 0 T tmp 61 T oper
  • c++---构造函数以及new和delete的使用

    目录 一 构造函数和析构函数的语法 二 构造函数的分类和调用 三 拷贝构造函数的调用时机 1 用已经创建好的对象来初始化新的对象 2 用值传递的方式 给函数参数传值 3 以值的方式 返回局部对象 四 构造函数调用规则 五 初始化列表 六 类
  • 函数(new)

    函数 xff08 new 一 字符串处理函数 1 字符串的输入 xff08 1 xff09 scanf span class token macro property span class token directive keyword i
  • C++(1) 指针 new 和delete

    1 概念 new typeName pointer name 61 new typeName delete delete pointer name 注意 xff1a 1 new之后要判断 xff0c 指针是否为NULL xff0c 内存被耗
  • C++的new

    C 43 43 中的new其实是一个很糊弄人的术语 xff0c 它有两种不同的含义 xff0c new运算符 xff08 new operator xff09 和new函数 xff08 operator new xff09 xff0c 值得
  • New Timeline的Toolbar样式设计

    最近在做新版的Timeline xff0c Toolbar Menu 的功能基本完成 xff0c 因此把截图拿出来与各位博友分享一下 新版Timeline HTML版本 主页面 xff1a 这次主要讲解一下Toolbar Menu 的功能
  • django连接elasticsearch失败Failed to establish a new connection: [Errno 113] No route to host[Errno 111]

    做django商城项目时报错 错误信息 urllib3 exceptions NewConnectionError lt urllib3 connection HTTPConnection object at 0x7fa6b2537390
  • new 、 delete 、 malloc 、 free 关系

    1 new delete malloc free 关系 delete 会调用对象的析构函数 和 new 对应 free 只会释放内存 xff0c new 调用构造函数 malloc 与 free 是 C 43 43 C 语言的标准库函数 x
  • c++new操作符笔记

    c 43 43 new语句 功能 xff1a 堆区开辟一组数据 语法 xff1a new 数据类型 注意点 xff1a new创建的数据会返回该数据对应的类型指针 xff0c 另外堆区开辟的数据由程序员手动释放
  • Java实现判断是否为最新版本方法

    判断是否为最新版本方法 将版本号根据 切分为int数组 比较 param localVersion 本地版本号 param onlineVersion 线上版本号 return 是否为新版本 throws IllegalArgumentEx
  • 柯理化、mergeOptions、new的实现原理、reduce、flat

    1 什么是反柯理化 怎么实现 反柯里化 是一个泛型化的过程 它使得被反柯里化的函数 可以接收更多参数 Function prototype unCurrying function var that this return function
  • memset in C++ and C

    definition memset是计算机中C C 语言函数 将s所指向的某一块内存中的前n个 字节的内容全部设置为ch指定的ASCII值 第一个值为指定的内存地址 块的大小由第三个参数指定 这个函数通常为新申请的内存做初始化工作 其返回值
  • 20个常见的Java错误以及规避方法

    原文 50 Common Java Errors and How to Avoid Them Part 1 作者 Angela Stringfellow 翻译 雁惊寒 译者注 本文介绍了20个常见的Java编译器错误 每种错误都包含了代码片

随机推荐