new § obj() p表示分配了空间的指针,obj()表示一个对象的构造
补充:
new为 new operator 用户不能重载,该操作符就是平时使用的,它会调用operator new 即标准库定义的,并且调用对应的构造方式,无论是一般类型还是类类型; place new 仅仅对分配了的空间进行赋值.
new()和new[] 问题,看看allocator.allocate
//测试关于类的new 操作符相关 classF { public: int a; int b; //构造器初始化顺序时按照变量位置进行的 F(int c, int d) : F(c, d) { this->p = p; } F(int c, int d) : a(c), b(d) { std::cout<<"构造函数"<<std::endl; } F(const F &f) { a = f.a; b = f.b; std::cout << "调用了拷贝构造" << std::endl; } ~F() { std::cout << "析构" << std::endl; delete p; } //重写一个new操作符,此处的代码实际就是new.h定义的一般new 的源码形式,仅仅是分配了空间 void *operatornew(size_t sz){ //此处的参数是给编译器使用的,并非是给程序员使用的 std::cout<<"调用op new"<<std::endl; void *p; // new_handler 以后说明,但是可以看出首先我们根据入口参数 sz的大小分配内存, // 如果sz为0 则令其为1 ,然后在while循环中调用malloc申请内存 // 直到 申请成功 或者 抛出异常或者 abort /* malloc (0) is unpredictable; avoid it. */ if (sz == 0) sz = 1;
while (__builtin_expect ((p = malloc (sz)) == 0, false)) { auto handler = std::new_handler (); if (! handler) _GLIBCXX_THROW_OR_ABORT(std::bad_alloc()); handler (); } return p; } }; //重写new操作符 voidopNew(){ F *f=new F(1,2); //次数的参数则是当作了汇编器调用构造器时使用的形参 PRINT(f->a); //打印宏 } // 调用op new // 构造函数 // 1
输出的结果说明了编译器new 的实质过程,如果你喜欢可以去看一眼反汇编代码
3.关于palce new
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//使用定位new voidtest3(){ F *f; F f2(1, 2); std::allocator<F> allocator; f = allocator.allocate(1); //f指针必须先是一块分配了空间的指针才行 ::new ((void*)f) F(f2); //表示直接使用编译器关键字new new ((void*)f) F(f2); //如果改成这样,至少在minGW编译器下会提示没有匹配到 F::operator new(sizetype, void*)' PRINT(f->a); //打印宏 } //构造函数 --->这是f2创建时调用的和palce new 无关 //调用了拷贝构造 -->这个拷贝构造则时临时对象的创建,最后该临时对象也没有发生析构,也就是说将该临时对象的内存给了p //1 //析构
对于palce new 在mingGW环境下,编译器会去从类内部匹配是否重写了place new, 如果没有就并没有去调用标准库定义的全局,此处就要主动使用
输出结果说明了palce new 的调用过程 就是将后者的内存使用拷贝拷贝,并且在palce new 函数的调用过程不会进行析构函数的调用
4.关于转发和移动语义