| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1426 人关注过本帖
标题:不散分,100分只给一个人(疑惑在代码中)
只看楼主 加入收藏
QQ346957135
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:148
专家分:658
注 册:2011-8-9
结帖率:100%
收藏
已结贴  问题点数:100 回复次数:21 
不散分,100分只给一个人(疑惑在代码中)
程序代码:
#include<iostream>
using namespace std;
class CStrtemp
{
public:
    CStrtemp(char *s);
    CStrtemp(const CStrtemp&);
    ~CStrtemp();
    void show();
    void set(char *s);
private:
    char *str;
};
CStrtemp::CStrtemp(char *s)
{
    cout<<"constructor."<<endl;
    str=new char[strlen(s)+1];
    if(!str)
    {
        cout<<"Allocation Error."<<endl;
        exit(1);
    }
    strcpy(str,s);
}

CStrtemp::CStrtemp(const CStrtemp& temp)
{
    cout<<"copy constructor."<<endl;
    str=new char[strlen(temp.str)+1];
    if(!str)
    {
        cout<<"Allocation Error."<<endl;
        exit(1);
    }
    strcpy(str,temp.str);
}

CStrtemp::~CStrtemp()
{
    cout<<"destructor."<<endl;
    if(str!=NULL)
    {
        delete[] str;
    }
}

void CStrtemp::show()
{
    cout<<str<<endl;
}
void CStrtemp::set(char *s)
{
    delete[] str;
    str=new char[strlen(s)+1];
    if(!str)
    {
        cout<<"Allocation Error."<<endl;
        exit(1);
    }
    strcpy(str,s);
}
CStrtemp Input(CStrtemp temp)
{
    char s[20];
    cout<<"Please input the string:";
    cin>>s;
    temp.set(s);
    return temp;
}

int main()
{
    CStrtemp A("hello");
    A.show();
    CStrtemp B=Input(A);//此处对象B的创建不需要调用复制构造函数吗,形式上为对象复制的一般格式<类名><对象2>=<对象1>;,为什么没调用?
    A.show();
    B.show();
    return 0;
}


















图片附件: 游客没有浏览图片的权限,请 登录注册
搜索更多相关主题的帖子: 100分 cha 一个人 
2011-10-02 11:21
hoho568
Rank: 5Rank: 5
等 级:职业侠客
帖 子:101
专家分:378
注 册:2009-7-14
收藏
得分:100 
这是C++的代码优化:
如果一个临时对象作为返回值被立即赋给另一个未构造对象,这个临时对象本身将被构造到被赋值对象在内存中的位置,即引用。
所以少了一次构造函数的调用。然而,实际上是减少了一次拷贝构造函数和一次临时对象的析构。相当于没有产生临时对象,但事实上是产生了临时对象。
调用复制构造函数都是真正的产生了临时对象。

可能有点绕,说的简单一点就是: CStrtemp B=Input(A);相当于B成为了临时对象的引用(和引用还是由区别,毕竟B不是引用),所有没有调用拷贝构造函数。同样的,也没有调用B的构造函数;

如果你细心的话应该注意到另外一个问题,就是你的临时对象也没有调用析构函数;B=Input(A);这个函数返回时会调用拷贝构造函数,同时函数里面的对象调用了析构函数,同时临时对象在赋值(或者初始化)完成后,应该调用析构函数,所以少一个析构函数。原因就是并没有析构,而是将这部分内存空间给了对象B;
程序代码:
int main()
{
    CStrtemp A("hello");
    A.show();
    CStrtemp B("fdf");
    B = Input(A); 
    system("pause");
    return 0;
}

对你的程序稍微修改,就可以看到函数返回过程是有两个析构函数的,分别是函数里面的对象和临时对象。这就不难理解了吧。
2011-10-02 14:15
pangding
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:北京
等 级:贵宾
威 望:94
帖 子:6784
专家分:16751
注 册:2008-12-20
收藏
得分:0 
你怎么断言的它没有调用呀。


我觉得是下面这个流程。不知道和楼主理解的一样不一样。

constructor.  构造A
hello  输出A
copy constructor.   构造input函数的那个形参temp
Please input the string:abcd
copy constructor.  构造B
destructor.  析构temp
hello  输出A
abcd 输出B
destructor.  析构B
destructor.  析构A


[ 本帖最后由 pangding 于 2011-10-2 15:11 编辑 ]
2011-10-02 15:10
QQ346957135
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:148
专家分:658
注 册:2011-8-9
收藏
得分:0 
回复 2楼 hoho568
你的第二句话貌似能合理的解释我的问题,但不够充分;下面的说明我想指出一点,在函数内返回对象时调用了复制构造函数创建临时对象,再将临时对象的值复制给B,然后临时对象就析构了。所以有输出的第一个destructor。关于那个形参,传递实参时调用了一次复制构造函数,但没有析构。书上没说明这点,我猜想形参随着函数的调用结束本来就该释放内存的,所以没必要析构。我想再等等,看有没有跟充分的解释。

A real warrior never quits.
2011-10-02 15:48
QQ346957135
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:148
专家分:658
注 册:2011-8-9
收藏
得分:0 
回复 3楼 pangding
第二个copy constuctor不是构造B而是构造临时对象才调用的;书上有明确说明。

A real warrior never quits.
2011-10-02 15:50
hoho568
Rank: 5Rank: 5
等 级:职业侠客
帖 子:101
专家分:378
注 册:2009-7-14
收藏
得分:0 
以下是引用QQ346957135在2011-10-2 15:48:53的发言:

你的第二句话貌似能合理的解释我的问题,但不够充分;下面的说明我想指出一点,在函数内返回对象时调用了复制构造函数创建临时对象,再将临时对象的值复制给B,然后临时对象就析构了。所以有输出的第一个destructor。关于那个形参,传递实参时调用了一次复制构造函数,但没有析构。书上没说明这点,我猜想形参随着函数的调用结束本来就该释放内存的,所以没必要析构。我想再等等,看有没有跟充分的解释。



晕,什么叫随函数结束了释放内存,没有析构。我不是给你举例子了吗。你看我给你修改的程序,你就需要析构的。。。
你的这个概念不是很正确,所有的类对象只要定义,就会析构。内存释放就是一个析构的过程。。。再好好想想吧。。

看看我给你的修改的例子,好好理解一下吧。

[ 本帖最后由 hoho568 于 2011-10-2 16:22 编辑 ]
2011-10-02 16:21
QQ346957135
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:148
专家分:658
注 册:2011-8-9
收藏
得分:0 
回复 6楼 hoho568
那我想问一下,形参temp传递给临时对象后跑哪儿了,如果析构了的话怎么没输出destructor?

A real warrior never quits.
2011-10-02 16:30
QQ346957135
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:148
专家分:658
注 册:2011-8-9
收藏
得分:0 
回复 6楼 hoho568
你给的例子运行出现了,我分析了一下在对象的赋值时,类的数据成员中不能包括动态分配的数据,否则在最后析构时由于“浅复制”会出现错误,程序不能正常运行。

A real warrior never quits.
2011-10-02 16:49
hoho568
Rank: 5Rank: 5
等 级:职业侠客
帖 子:101
专家分:378
注 册:2009-7-14
收藏
得分:0 
以下是引用QQ346957135在2011-10-2 16:30:58的发言:

那我想问一下,形参temp传递给临时对象后跑哪儿了,如果析构了的话怎么没输出destructor?



没有输出吗?不是输出了吗。
2011-10-02 16:56
QQ346957135
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:148
专家分:658
注 册:2011-8-9
收藏
得分:0 
回复 9楼 hoho568
输出的第一个destructor是析构临时对象的,后面两个析构B和A,哪儿输出了?

A real warrior never quits.
2011-10-02 16:58
快速回复:不散分,100分只给一个人(疑惑在代码中)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019238 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved