c++new语法
2010-06-04 23:09:00 intheway_acm 阅读数 993

#include <iostream>

using namespace std;

struct Node{

    int u;

    Node(int uu = 0):u(uu){

        //cout << "create" << endl;

    }

    ~Node(){

        u = -1000;

        //cout << "delete/n";

    }

};

 

 

int main(){

    Node mem[100];

    Node *p = mem;

    Node *q = new (p)Node(10);

 

    cout << p << ' ' << q << ' ' << mem << endl;

    cout << q->u << endl;

    q->~Node();

    Node *r = new(p)Node(20);

    cout << r->u << endl;

    for(int i = 0; i < 10; ++i)

        cout << mem[i].u << endl;

    return 0;

}

上次同学做百度网上的题(话说他没怎么学过C++。。。)碰到一个题,上面就有这种new的放置语法,当时不太懂,看到书上才知道有这种用法。。。    
Node *q = new (p)Node(10); 就是从p为首地址分配一段内存给q,这段内存是已经预先开辟的,可能是用来共享的吧,所以不用的时候要掉用析构函数而不是delete。

2015-04-10 11:55:38 vrxan0w0 阅读数 227

C++ 指定新建对象的内存分配策略

有一个类A,定义一个对象,一般有两种方法:
1. 定义一个变量:

 A a;

如果是定义的全局变量,则对象是分配在数据段。如果是定义的局部变量,则对象是分配在栈中。
2. 利用placement new:

A *pA = new A

通过new新建的对象,对象是分配在堆中,采用的是标准库的内存分配算法。

下面介绍一种new的用法,可以做到对象内存的来源或者分配策略可控。直接看代码:

#include<iostream>
using namespace std;
class A
{
public:
    A(){data = 10;};
    A(int i){data = 5;};
    int data;
};

int main(int n,char *argv[])
{
    void *p = new char[sizeof(A)];//用new只是示例,实际应用时可以使用自定义的内存分配策略
    A *pA = new(p) A;//这句话就是本篇文章的关键了
    cout<<pA->data<<endl;

    //带参数的构造方法
    void *p2 = new char[sizeof(A)];
    A *pA2 = new(p2) A(5);
    cout<<pA2->data<<endl;
    //内存释放省略
    return 0;
}

注意,一般来说new和delete是成对使用的。但placement new生成的对象,不一定能使用delete删除,需要自己调用对象的析构函数,然后手动释放内存。
因为placement new的内存可以不是从堆里面申请的,但delete在释放内存时会默认对象的内存是从堆申请的。

应用场景在哪呢?比如需要频繁创建对象,如果我们嫌new的内存分配算法太坑,那么我们就可以实现自己的内存管理,然后写一个Allocator,利用placement new的语法,就可以控制对象所在的内存了。

2017-03-03 20:20:01 xibeichengf 阅读数 472

今天在学习boost的共享内存时,看网上的一段代码。主要实现的功能是一个进程写一份跟踪数据至共享内存缓存区,另一个进程一个接一个打印出来。第一个进程写跟踪数据,然后等待,直到另一个进程打印这份数据。为达到此目的,我们可以使用两个条件变量:第一个用于阻塞发送者直到第二个进程打印出此消息,第二个用于阻塞接受者直到缓存区中有数据供打印。

但是,下面的代码让我感到很是困惑:

//Map the whole shared memory in this process
mapped_region region
    (shm                       //What to map
     ,read_write //Map it as read-write
     );
 
//Get the address of the mapped region
void * addr       = region.get_address();
 
//Construct the shared structure in memory
trace_queue * data = new (addr) trace_queue;

其中trace_queue是一个结构体,也就是我们共享内存中存放的东西。其中,addr是结构体trace_queue已申请的地址。第一次看到这个表达很是不解,通常如果我们要获得一个结构体的指针,应该用下面的方式来申请:

trace_queue * data = new trace_queue;
我还用如下我所能理解的代码来替换上述写法

void *addr = region.get_address();

//Construct the shared structure in memory
trace_queue * data = static_cast<trace_queue *> (addr);

这个逻辑很容易理解,通过static_cast将指向申请的共享内存地址的指针强制转换为指向trace_queue结构体的指针。

但是执行的时候,打印进程却有segmentation fault的错误。通过gdb调试,找到如下错误信息:

Program received signal SIGSEGV, Segmentation fault.
pthread_cond_signal@@GLIBC_2.3.2 ()
    at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S:69
69		movl	MUTEX_KIND(%rcx), %r11d
这让我感到不解。于是我就上网查找如trace_queue * data = new (addr) trace_queue的语法。

原来这是C++的placement new语法。placement new允许你在已经获得的内存上构造一个对象。你可能这样做是出于优化的目的(你需要重新多次构造一个对象)这比每次都要重新申请内存来说会快很多。

此文提到:标准C++也支持placement new操作符,用来在一个预先申请的buffer上构造一个对象。这当要建造一个内存池,一个垃圾收集器或者仅仅是性能和执行安全性是至关重要的(没有内存申请失败的危险,因为内存已经申请到了,并且在一个预分配的buffer上构造一个对象更省时间):

char *buf  = new char[sizeof(string)]; // pre-allocated buffer
string *p = new (buf) string("hi");    // placement new
string *q = new string("hi");          // ordinary heap allocation
你可能也想确定在特定至关重要的部分代码中没有申请内存失败的风险(可能你工作在一个和平使者的项目),你那种情况下,有应该就像使用placement new语法了。

那使用了placement new语法,该如何释放内存呢?你不需要释放在内存buffer上的所有的对象。相反,你只需要删除原始buffer即可。你必须直接手动地调用你的类的析构函数。

这里有关于placement delete的说明。

2018-05-18 09:53:46 u014287775 阅读数 125

转载自:https://blog.csdn.net/intheway_acm/article/details/5648604

#include <iostream>

using namespace std;

struct Node{

    int u;

    Node(int uu = 0):u(uu){

        //cout << "create" << endl;

    }

    ~Node(){

        u = -1000;

        //cout << "delete/n";

    }

};

 

 

int main(){

    Node mem[100];

    Node *p = mem;

    Node *q = new (p)Node(10);

 

    cout << p << ' ' << q << ' ' << mem << endl;

    cout << q->u << endl;

    q->~Node();

    Node *r = new(p)Node(20);

    cout << r->u << endl;

    for(int i = 0; i < 10; ++i)

        cout << mem[i].u << endl;

    return 0;

}

上次同学做百度网上的题(话说他没怎么学过C++。。。)碰到一个题,上面就有这种new的放置语法,当时不太懂,看到书上才知道有这种用法。。。    
Node *q = new (p)Node(10); 就是从p为首地址分配一段内存给q,这段内存是已经预先开辟的,可能是用来共享的吧,所以不用的时候要掉用析构函数而不是delete。
2016-08-31 23:15:00 weixin_34284188 阅读数 13

这里有一篇Blog有讲解这个问题->C++中创建对象的时候加括号和不加括号的区别

看过一遍之后大概懂了,结论就是:

对于自定义class来说,new className; 和 new className(); 的作用完全相同,均是调用自定义class的无参构造函数。如果这个自定义class仅有带参数的构造函数,则上面两种用法均会报错。

对于内置类型来说,new typeName; 和 new typeName(); 的作用不完全相同。虽然它们均调用了内置类型的默认构造函数,但是 new typeName(); 的用法会对对象进行初始化。


为了防止忘记,自己来写一段代码试试效果:

//MyData.h
#include "stdio.h"
#include <iostream>

class MyData
{
public:
    MyData();
    MyData(int nNo);
    
    void showMe();
    
private:
    int m_nNo;
};

//MyData.cpp
int main()
{
    std::cout << "---自定义Class----" << std::endl;
    MyData data1;       //使用默认构造函数,构造一个MyData对象
    std::cout << "-----------------" << std::endl;
    MyData data2();     //声明一个返回值为MyData的函数,这里不会有输出
    std::cout << "-----------------" << std::endl;
    MyData data3(1);    //使用带参构造函数,构造一个MyData对象
    std::cout << "-----------------" << std::endl;
    
    MyData *pData1 = new MyData;    //使用默认构造函数
    std::cout << "-----------------" << std::endl;
    MyData *pData2 = new MyData();  //使用默认构造函数
    std::cout << "-----------------" << std::endl;
    MyData *pData3 = new MyData(88);//使用带參构造函数
    std::cout << "-----------------" << std::endl;
    
    pData1->showMe();
    std::cout << "-----------------" << std::endl;
    pData2->showMe();
    std::cout << "-----------------" << std::endl;
    pData3->showMe();
    std::cout << "-----------------" << std::endl;
    
    
    std::cout << "-----内置Class----" << std::endl;
    int nNo1;       //定义一个int类型变量
    int nNo2();     //声明一个返回值为int的函数
    int nNo3(1);    //定义一个int类型变量,初始化为1
    
    std::cout << "Int->" << nNo1 << std::endl;
    std::cout << "Int->" << nNo2 << std::endl;
    std::cout << "Int->" << nNo3 << std::endl;
    
    int *pNo1 = new int;        //使用默认构造函数
    int *pNo2 = new int();      //使用默认构造函数(不确定这里会不会进行初始化,是否与new int;的用法有什么不同)
    int *pNo3 = new int(88);    //使用带参构造函数
    
    std::cout << "Int->" << pNo1 << std::endl;  //输出地址
    std::cout << "Int->" << pNo2 << std::endl;  //输出地址
    std::cout << "Int->" << pNo3 << std::endl;  //输出地址
    
    std::cout << "Int->" << *pNo1 << std::endl; //输出值
    std::cout << "Int->" << *pNo2 << std::endl; //输出值
    std::cout << "Int->" << *pNo3 << std::endl; //输出值
    return 0;
}

上面的代码我自己运行过,可能是因为运行的环境有所不同,得出的结果并没有明确的反映文章开头部分所说,这两种用法对于内置对象的区别。(也有可能是c++11版关于上述方法的功能修改过了)。上面代码输出如下:

---自定义Class----
MyData()
-----------------
-----------------
MyData(int)
-----------------
MyData()
-----------------
MyData()
-----------------
MyData(int)
-----------------
I am No. 0
-----------------
I am No. 0
-----------------
I am No. 88
-----------------
-----内置Class----
Int->1
Int->1
Int->1
Int->0x6080000043f0
Int->0x608000004400
Int->0x6080000043e0
Int->0
Int->0
Int->88

[C++] c++ new() 与new[]的区别

阅读数 901

new和delete运算符用于动态分配和撤销内存的运算符new用法:     1.  开辟单变量地址空间        1)newint; //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int*a=newint即为将一个int类型的地址赋值给整型指针a.         2)int*a=newint(

博文 来自: robby_chan

C++的new

阅读数 379

写的很不错的一篇文章,对new讲的比较深入。只是对最后delete[]p这部分有些怀疑。因为所有的书上对简单类型的数组,也要求用delete[],而它说简单类型,也就是无需析构函数的数组,可以直接deletep。并且delete时如何得知它的长度呢,既然没有多余的字节记录它本身长度。===============分隔线=================================

博文 来自: ts_rfl

C++ new

阅读数 513

C++中,new其实有三种含义: 1.newoperator2.operatornew3.placementnew我们最常用的用法是A*a=newA();这里的new就是newoperator,它一共包含了三步:1.分配内存2.调用A的构造函数3.返回内存指针第一步,分配内存,实际就是使用operatornew,效果和malloc类似,直接调用的话,如下:a= operato

博文 来自: zhf9208

C++ new

阅读数 464

“new”是C++的一个关键字,同时也是操作符。关于new的话题非常多,因为它确实比较复杂,也非常神秘,下面我将把我了解到的与new有关的内容做一个总结。new的过程当我们使用关键字new在堆上动态创建一个对象时,它实际上做了三件事:获得一块内存空间、调用构造函数、返回正确的指针。当然,如果我们创建的是简单类型的变量,那么第二步会被省略。假如我们定义了如下一个类A:clas

博文 来自: ym19860303

c++ new

阅读数 210

1993年前,C++一直要求在内存分配失败时operator new要返回0,现在则是要求operator new抛出std::bad_alloc异常。很多C++程序是在编译器开始支持新规范前写的。C++标准委员会不想放弃那些已有的遵循返回0规范的代码,所以他们提供了另外形式的o

博文 来自: lhf1985314
没有更多推荐了,返回首页