为什么很多人都喜欢new一个类,而不是直接声明一个对象呢?
我看很多人写的代码都喜欢这样写(示例)
MyClass* pc = new MyClass();
pc->doSome();
...
delete pc;
为什么非要去new呢?而且这样很容易忘记最后delete。
为什么不按照下面这样呢?
MyClass c;
c.doSome();
....
我觉得这样很好阿,而且不需要delete。难道第一种写法有什么特别的好处吗?看到很多代码都是第一种写法。谢谢。
问题点数:100、回复次数:31Top
1 楼iambic()回复于 2006-05-03 12:31:25 得分 0
指针在传值和多态使用上比较安全。Top
2 楼fiftymetre(50米深蓝)回复于 2006-05-03 12:34:33 得分 0
这二段代码在不同的地方,的用处不同的。主要还是看你去用在什么地方的,看它的生命期,作用域之类的来的。Top
3 楼goodboy1881(积木)(谁都别拦着我在水源升星)回复于 2006-05-03 12:40:35 得分 0
指针才是王道。。。
内存管理,多态。。。Top
4 楼goodchan(想飞之心,永远不死!!!)回复于 2006-05-03 12:50:51 得分 0
MyClass c;
c.doSome();
---------------------------
静态分配内存,在生成程序的时候已经确定它的内存如何分配
MyClass* pc = new MyClass();
pc->doSome();
delete pc;
---------------------------
动态分配内存,可以在程序运行的时候来决定如何分配,这样可以大大减少内存的浪费。
这些几乎所有的教科书上都有说明的,看书就行。Top
5 楼goodchan(想飞之心,永远不死!!!)回复于 2006-05-03 13:04:35 得分 0
而且,C++ 的一个重要特性--多态,是通过指针或者引用来使用的。如果用静态内存分配方式,无法使用。
例如:
class A
{
public:
virtual void print() { std::cout << "A::print()\n"; }
};
class B
{
public:
virtual void print() { std::cout << "B::print()\n"; }
};
A *p = new B; // 基类 A 的指针,可以指向 派生类 B 的对象
p->print(); // B::print()
// 因为函数 print() 在基类 A 里面是 virtual 函数,同时在派生类 B 里面被修改过,
// 所以这里使用的是派生类 B 的 print(),而不是基类 A 的 print()
如果 A 里面的 print() 不是 virtual 又或者它虽然是 virtual 但在 B 里面没有被改写,那么
p->print(); // 使用的是 A::print()
如果用静态内存分配方式,则:
A a; a.print(); // 只能用 A::print()
B b; b.print(); // 只能用 B::print()
不会有:
A *p = new B;
p->print(); // 这里究竟是 A::print() 还是 B::print(),要看 print() 的性质
这些东西书上都有说的。建议多看看Top
6 楼zihui(zihui)回复于 2006-05-03 13:36:07 得分 0
谢谢各位的回帖。多态这一点我是明白的。其它的我还有点疑问。
1。iambic兄说“指针在传值和多态使用上比较安全。”为什么“指针在传值上比较安全”?我实在不清楚安全在哪里?
2。如果实际的程序中没有多态的因素,是new出来好呢还是直接声明出来呢?我个人总是觉得new出来是一个开销很大的事情。
谢谢。Top
7 楼powerpretty(intothechaos)回复于 2006-05-03 16:26:22 得分 0
用指针可以使用多态,声明对象就不能体现多态Top
8 楼kingoffighting()回复于 2006-05-03 16:52:08 得分 0
查MSDN的strstr方法Top
9 楼iambic()回复于 2006-05-03 16:57:47 得分 0
如果是作为函数的参数和返回值传递,可以避免对象的赋值拷贝。而赋值拷贝是很容易出现问题的。Top
10 楼sankt(宠辱不惊,看庭前花开花落;去留无意,望天空云卷云舒.)回复于 2006-05-03 18:03:10 得分 20
各有其优缺点.
主要还是看功能需求和当时的实际情况.
比如说多态的实现,这时候就必须使用指针或引用了.
Top
11 楼yuanchuang(元创)回复于 2006-05-03 18:41:24 得分 10
个人观点:主要还是考虑作用域吧。Top
12 楼Wolf0403(废人:独活十年~心如刀割)回复于 2006-05-03 18:51:02 得分 20
支持楼上元创。
如果仅在一个局部作用域中需要一个对象的存在(如,一个函数体内、一个类内、一个 for block 内等),那么直接在栈上(就是,不用 new 单独在堆上分配)是非常合理的。如果需要一个对象的生命期比它所在的代码范围更长,或者需要多处共享这个对象,可能就需要在堆上分配。
至于说多态相关的。。。
{ A *p = new B(); p->whatever(); delete p }
和
{ B b; b.whatever(); }
有区别么?一个很经典的差劲示例而已。
只有当作为函数参数时,传递指针/引用与按值传递对象才会有非常显著的区别。Top
13 楼Jedimaster(CRH = 耻辱号)回复于 2006-05-04 09:21:51 得分 0
在HEAP里动态分配可以在后面对对象的操作中仅仅传递指针而且可以方便的实现多态
但是要注意不要内存泄露了
father* ptr = new father();
ptr = new son();//第一个father丢了Top
14 楼Maconel(Maconel)回复于 2006-05-04 09:22:28 得分 20
我认为主要是作用域上的差别,一般能不用new,我都不用new的。
至于多态和函数参数,都不是问题:
多态可以这样用:
B b;
A* p = &b;
p->dosomething();
传参数也是一样:
函数定义:
void fn(B* b);
调用:
fn(&b);
或者这样定义:
void fn(B& b);
调用:
fn(b);
Top
15 楼xhwen()回复于 2006-05-04 09:38:03 得分 0
学习Top
16 楼hundlom(托克维尔)回复于 2006-05-04 10:17:01 得分 10
用new是在堆上申请空间,堆的空间跟物理内存大小有关。
而静态的声明是在栈上申请空间。栈的大小有限制。Top
17 楼WilliamJ(威廉J)回复于 2006-05-04 10:17:21 得分 0
原因很多,但主要有两个:一,为了更好的控制对象的生命期,由程序员决定.二,为了更好的使用多态.Top
18 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-05-04 11:50:32 得分 0
1 可以将创建聚合对象的开销延后
2 句柄模式Top
19 楼ugg(逸学堂(exuetang.net))回复于 2006-05-04 12:52:28 得分 0
new是得对象可以由用户自己管理。
用户来决定什么时候创建对象,什么时候消耗对象。
比如lz来考虑在运行时刻添加数据成员(一个典型得例子就是用结构体存储用户信息,输入多个用户信息),这里得多个可能是0也可能是100,我们不好提前分配空间,最好在运行时刻添加一个用户,new一个结构体。Top
20 楼CrazyAzreal(顶..真系稳食艰难!)回复于 2006-05-04 14:49:31 得分 0
我有一段时间也有这样的迷惑,不过我听我的一个同事说,说直接对地址操作执行速度高一点Top
21 楼rorl(在路上 是我生命的远行)回复于 2006-05-04 17:15:27 得分 5
自己给自己总结一下:
1。考虑变量的作用域。如果作用域不限于一个模块内,那么在模块内需要用new从堆上创建对象。不然就可以用声明对象的方式。
2。多态性。当然先声明对象,然后用基类指针指向对象也可以,但这样的程序看上去不够美观。
Top
22 楼pottichu(拉拉是头猪)回复于 2006-05-04 18:14:44 得分 0
用指针有很多好出,楼主漫漫会发现的。Top
23 楼MagicCarmack(MagiC++)回复于 2006-05-04 19:08:06 得分 0
继rorl(用C语言,写B+树,得A成绩) 分析
1、考虑变量的作用域。NEW分配空间必须由你自己释放,局部变量在它作用局域内使用完后会自动释放!比如在函数内NEW分配的空间就可以在函数结束后继续使用,局部变量就不可以!
2。多态性。多态最基本的需要就是指针
Top
24 楼houdy(致力于图像/图形领域,成为有思想的程序员)回复于 2006-05-04 19:23:59 得分 5
1 可以将创建聚合对象的开销延后
2 句柄模式
>>>> 如何理解?能不能再详细一点?Top
25 楼zidanjxnu(有人活着!)回复于 2006-05-04 21:12:59 得分 0
学习中……
以我的认识,如果不用多态,而且这个生命周期也很短。我觉得我还是不会去new 一个,毕竟这里还是需要去释放,这里就有泄漏的可能。呵呵Top
26 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-05-05 00:54:19 得分 5
句柄模式是指将所有对内部对象的操作转发到一个成员变量,这样可以保护类的非公开成员的访问级别不被重载的类所更改
创建聚合对象的开销有可能很大,例如,聚合对象可能在另一个套间或者另一台计算机上.这时候可以在第一次使用到这个聚合对象提供的功能时再创建这个对象Top
27 楼houdy(致力于图像/图形领域,成为有思想的程序员)回复于 2006-05-05 10:06:06 得分 0
句柄模式是指将所有对内部对象的操作转发到一个成员变量,这样可以保护类的非公开成员的访问级别不被重载的类所更改
>>>> 你说的句柄模式是不是"private implemenatation"?Top
28 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-05-05 10:13:15 得分 5
// MyClass.h
class MyClassImpl; // forward declaration
class MyClass {
public:
MyClass();
~MyClass();
int foo();
private:
MyClassImpl *m_pImpl;
};
......
int MyClass::foo()
{ return m_pImpl->foo(); }
Top
29 楼pgmsoul(游侠)回复于 2006-05-05 10:35:11 得分 0
我倾向于用
A a;
a.func();
而不是
A* pa = new A;
pa->func();
delete pa;
删除指针的确是麻烦.
这两者在性能上是相同的(差不多).
但如果有很多的对象(比如10000个以上),这时候可以用数组,但显然会占用栈内存,所以应该用指针.这是主要差别.new 出来的开销不一定大.
至于多态,静态声明就不可以使用吗?不明白.
作用域更是不着边,学C++的应该很清楚.
说到安全性,我认为,永远不要传递一个类的值,C++应该取消这种默认方式,看着吧,会有这一天的.甚至,C++应该把指针做为一个独特的类型,严格的和普通类型区别.Top
30 楼Linux2001(闭关开发中)回复于 2006-05-05 15:32:07 得分 0
差别就是对于函数参数来讲,如果一个类比较大(应该可以理解什么是比较大型的类吧),那么传递指针的好处就是性能上比传递一个值要高非常非常的多,因为传值进函数还会在函数内部造成拷贝构造函数的调用,那么性能下降非常厉害,如果是函数内部声明局部变量,没有多态的考虑,那么使用声明对象的方式就可以了,这个上面和new 一个对象的差别不是很大!Top
31 楼pgmsoul(游侠)回复于 2006-05-07 10:07:17 得分 0
补充一点,new 因为用的是动态内存,所以在内存空间上是优化一些.但的确,new操作要申请内存,这个过程在速度上有非常大的损失,大概要用1000个整数操作的时间.Top




