C++的new

CShape* pShape;

pShape = new CLine();

pShape->draw();

CLine a;

a.draw();

这种方式声明对象有河区别??

问题补充:

什么时候用CLine a;这种方式

什么时候用pShape = new CLine(); 这种方式

声明一对象

 

其中你这两个例子执行结果是一致的!但为什么要用多态

 

最主要的使用是为不同派生使用同样的驱动,即一个单一接口或变量。

 

void AdvancedDraw()函数可以为不同派生内做高级绘图操作,这些派生类有,CLine, CCircle, CAngle等。则这样的函数为:

void AdvancedDraw(CLine &c);

void AdvancedDraw(CCircle &c);

vodi AdvancedDraw(Cangle &c);

以后每增加一个派生类需要增加一个处理函数,但是,如果利用多态,则只要一个函数

void AdvancdDraw(CShape &c)

{

// others

 c.draw();

}

这样会自动根据对象类型调用不同派生类的draw();

还有如

一个模块根据用户输入决定绘制操作,不利用多态则为:

 

CLine a;

CCircle b;

Cangle c;

swtch(sel)

{

  case 1: a.draw(); break;

  case 2: b.draw(); break;

  case 3: c.draw(); break;

}

以后增加新派生类,在这个模块中还需要增加变量,诸如d, e, f等。但利用多态则,只要一个变量来处理。如

CShape *a;

swtch(sel)

{

  case 1: a = new CLine; break;

  case 2: a = new CCircle; break;

  case 3: a = new Cangle; break;

}

a->draw();

这样代码需要修改的地方很少,减少出错的概率。

 

三种形式的new表达式

<1>    单个对象的动态分配

<2>    数组的动态分配

<3>    定位new表达式

------------------------------------------------------------------

<1>

#define TR(S) cout << #S" : " << S << endl

 

int *pi = new int(11); // initializer

TR(*pi);

int i = 22;

int *q = new int;   //assign

*q = i;

TR(*q);

 

*    因为new表达式是从堆上申请内存,但堆上空闲储存区是有限的,但空闲储存区内存耗尽时,导致new表达式失败,抛出bad_alloc异常

*    常见new错误    <1> delete表达式失败(内存泄漏 memory leak)    <2>对同以内存用2delete    <3>对象被释放后继续读写该对象

---------------------------------------------

auto_ptr (自动管理用new表达式动态分配的内存)

auto_ptr<int> pi(new int(11));

cout << *pi << endl;

pi的作用域跟普通变量的作用域一样的,pi的生命期结束时, 被释放

{

     auto_ptr<int> pi(new int(11));

}

cout << *pi << endl;        // error C2065: 'pi' : undeclared identifier

------------------------------------------------------------------------

auto_ptr<int> p1(new int(11));

auto_ptr<int> p2(new int(22));

cout << *p1 << endl;

cout << *p2 << endl;

p1 = p2;

cout << *p1 << endl;

//cout << *p2 << endl;   // error   这样p2被重置为0

if (p2.get() == 0)                        //  

cout << "p2 is alive" << endl;

p2.reset(new int(33));               // 只能这样重置p2

cout << *p2 << endl;

----------------------------------------------------------------------

auto_ptr<string> str1(new string("aaaaa"));

str1.reset(new string("bbbbbbbbb"));

cout << *str1 << endl;

str1->assign("ccccc");   //这样更有效...

cout << *str1 << endl;

需要包含头文件string memory 刚才一时情急忘了加#inlcude<string> 然后居然把输出写成cout << str1 << endl;没有解引用...呵呵...- -!

* auto_ptr对象并不比直接使用指针代价高,大多操作都是inline

*auto指针的是用指针的所有权方式,当把一个指针赋值给另一个指针的时候,后者拥有所有权,前者不再指向原来的对象,被赋值为0.

---------------------------------------------------------------------------

int *p = 0;

if ( !p )

   cout << "p is non-initialize" << endl;

auto_ptr<int> p2;      // 从这里也能看出跟普通指针的不同, auto_ptr自动将对象初始化为0

if (!p2.get())

   cout << "p2 is non-initialize" << endl;

*使用普通指针是可以用是否为0,auto_ptr不可以,auto_ptrget()返回对象内部的底层指针(reset()来重置一个底层指针),

----------------------------------------------------------

*    不能用一个指向"内存不是用new分配的"指针来初始化或者赋值auto_ptr指针

*    不能让两个auto_ptr对象拥有空闲存储区内同一对象的所有权()

 

2>数组的动态分配

int *pi = new int[11];   // 分配有11个元素的动态数组

int (*pia)[11] = new int [22][11];   //分配一个含有 22 * 11 个元素的二维数组

*    动态分配的数组不能给出初始化值,一般在 for 循环中一个一个的初始化

   eg:           for(int i = 0; i < 11; i++)

                  pi[i] = 0;

*    动态数组的第一维不必是常量值, 这样就不必在编译时刻就知道维数,我们可以根据需要分配大小合适的内存单元

*    释放动态数组:        delete [ ] pi;    如果不小心忘记了空括号,编译器不会捕捉到这个错误, 务必要小心

*     一般为了避免动态分配数组带来的内存管理的问题, 我们使用c++ 标准库vector, list or string 会自动管理内存的容器类型

---------------------

常量对象的动态分配

const int *pic = new const int(1024);

*     const 对象必须被初始化, 否则会编译错误,(因此我们也不能创建const数组,因为const数组不能被初始化,除了类数组)

*    new表达式返回的值作为初始值的指针必须是一个指向const类型的指针. eg: const int

*    它的生命期同样也用delete表达式来结束 eg: delete pic;

=============================================================

<3>定位new表达式(placement new expression)

形式: new (place_address) type-specifier

头文件: #include <new>

place_adress必须是指针

eg:

int *buf = new int[2];

int *pb = new (buf) int;

*pb = 11;

cout << *pb << endl;             // 11

cout << *buf << endl;            // 11

cout << pb << endl;                 // 同样pbbuf的所指向的地址也是相同的

cout << buf << endl;                //

 

int *pp = new (buf + 1) int;

*pp = 22;

*    因为定位符并不分配内存,所以我们并没有与定位符相匹配的delete表达式, 对此我们需要删除的是分配内存的指针,在上面的例子中我们 delete [] buf;

 

newdelete运算符用于动态分配和撤销内存的运算符

 

new用法:

 

          1.     开辟单变量地址空间

 

               1)new int;  //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给整型指针a. 

 

               2)int *a = new int(5) 作用同上,但是同时将整数赋值为5

 

          2.     开辟数组空间

 

               一维: int *a = new int[100];开辟一个大小为100的整型数组空间

 

               二维: int *a = new int[5][6]

 

               三维及其以上:依此类推.

 

         一般用法: new 类型 [初值]

 

delete用法:

 

          1. int *a = new int;

 

               delete a;   //释放单个int的空间

 

          2.int *a = new int[5];

 

               delete [] a; //释放int数组空间

 

 

 

          要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问.

 

          newdelete可以动态开辟,撤销地址空间.在编程序时,若用完一个变量(一般是暂时存储的数组),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它

int *a = new int[5][6]

vc里行不通

应该是

int*a[6]=new int[5][6]

 

c++new的几种用法

在释放时有区别。你用new申请的堆内存,你有释放它的义务和责任,你必须用delete释放它,否则会造成内存泄漏,即memory   leak,   对于一个对象而言,释放它的方式取决于你的构造函数,是否用到new申请内存。但是例2的指针是一定要用delete释放的。

 

c++中,new的用法很灵活,这里进行了简单的总结:

 

1. new() 分配这种类型的一个大小的内存空间,并以括号中的值来初始化这个变量;

 

2. new[] 分配这种类型的n个大小的内存空间,并用默认构造函数来初始化这些变量; 

 

#include<iostream>

 

#include<cstring>

 

using namespace std;

 

int main(){   

 

//char* p=new char("Hello");

 

//error分配一个char(1字节)的空间,                                 

 

//"Hello"来初始化,这明显不对   

 

char* p=new char[6];   

 

//p="Hello";                

 

//不能将字符串直接赋值给该字符指针p,原因是:                                

 

//指针p指向的是字符串的第一个字符,只能用下面的                                

 

//strcpy   

 

strcpy(p,"Hello");   

 

cout<<*p<<endl;              //只是输出p指向的字符串的第一个字符!   

 

cout<<p<<endl;               //输出p指向的字符串!   

 

delete[] p;  

 

 return 0;}

 

输出结果:

 

H

 

Hello

 

3. 当使用new运算符定义一个多维数组变量或数组对象时,它产生一个指向数组第一个元素的指针,返回的类型保持了除最左边维数外的所有维数。例如: 

 

 int *p1 = new int[10];  

 

返回的是一个指向int的指针int* 

 

int (*p2)[10] = new int[2][10];

 

new了一个二维数组, 去掉最左边那一维[2], 剩下int[10], 所以返回的是一个指向int[10]这种一维数组的指针int (*)[10]. 

 

int (*p3)[2][10] = new int[5][2][10];  new了一个三维数组, 去掉最左边那一维[5], 还有int[2][10], 所以返回的是一个指向二维数组int[2][10]这种类型的指针int (*)[2][10].    

 

#include<iostream>

 

#include <typeinfo>

 

using namespace std;

 

 int main() {

 

int *a = new int[34];

 

int *b = new int[];

 

int (*c)[2] = new

 

int[34][2];

 

int (*d)[2] = new int[][2];

 

int (*e)[2][3] = new int[34][2][3];

 

 int (*f)[2][3] = new int[][2][3];

 

 a[0] = 1;

 

 b[0] = 1; //运行时错误,无分配的内存,b只起指针的作用,用来指向相应的数据

 

 c[0][0] = 1;

 

d[0][0] = 1;//运行时错误,无分配的内存,d只起指针的作用,用来指向相应的数据

 

e[0][0][0] = 1;

 

f[0][0][0] = 1;//运行时错误,无分配的内存,f只起指针的作用,用来指向相应的数据

 

cout<<typeid(a).name()<<endl;

 

 cout<<typeid(b).name()<<endl;

 

 cout<<typeid(c).name()<<endl;

 

cout<<typeid(d).name()<<endl;

 

cout<<typeid(e).name()<<endl;

 

 cout<<typeid(f).name()<<endl;

 

delete[] a; delete[] b; delete[] c;

 

delete[] d; delete[] e; delete[] f;

 

}  

 

输出结果:

 

 int *

 

int *

 

int (*)[2]

 

int (*)[2]

 

int (*)[2][3]

 

int (*)[2][3]

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值