读书人

临时对象有关问题

发布时间: 2012-09-29 10:30:01 作者: rapoo

临时对象问题
以下是两段代码:

代码1:

C/C++ code
#include <iostream>using namespace std;class Point {private:  int x;  int y;public:    Point(int, int);    Point(const Point &);    ~Point();      Point operator =(Point);};Point::Point(int i, int j){     x = i;     y = j;      cout<<"调用一般构造函数"<<endl;}  Point::Point(const Point & p){    x = p.x;    y = p.y;    cout<<"调用拷贝构造函数"<<endl;}Point::~Point()  {    cout<<"调用析构函数"<<endl;  }Point Point::operator =(Point p){     x = p.x;     y = p.y;    cout<<"重载赋值运算符函数"<<endl;    return (*this);}int main( ){     Point pa(20, 35), pb(10, 10);    cout<<endl;    pa = pb;    cout<<endl;    return 0;}  


这是输出结果:

调用一般构造函数
调用一般构造函数

调用拷贝构造函数 //调用 = 重载运算符之前,会先调用拷贝构造函数,将pb赋值给形参Point P
重载赋值运算符函数
调用拷贝构造函数
调用析构函数
调用析构函数

调用析构函数
调用析构函数



代码2:

C/C++ code
#include <iostream>using namespace std;class Point {private:  int x;  int y;public:    Point(int, int);    Point(const Point &);    ~Point();      Point operator =(Point);};Point::Point(int i, int j){     x = i;     y = j;      cout<<"调用一般构造函数"<<endl;}  Point::Point(const Point & p){    x = p.x;    y = p.y;    cout<<"调用拷贝构造函数"<<endl;}Point::~Point()  {    cout<<"调用析构函数"<<endl;  }Point Point::operator =(Point p){     x = p.x;     y = p.y;    cout<<"重载赋值运算符函数"<<endl;    return (*this);}Point func(Point p){     cout<<"已经进入到func( )的函数体内"<<endl;    Point temp(5, 5);        return temp;}int main( ){     Point pa(20, 35), pb(1, 2);    cout<<endl;    pa = func(pb);    cout<<endl;    return 0;}  


这是输出结果:

调用一般构造函数
调用一般构造函数

调用拷贝构造函数
已经进入到func( )的函数体内
调用一般构造函数
调用拷贝构造函数
调用析构函数
调用析构函数
重载赋值运算符函数
/*
函数func()返回一个临时对象,将这个临时对象赋值给pa时,会调用 = 运算符重载函数,在调用 = 运算符重载函数之前,应该会去调用拷贝构造函数,将这个临时对象赋值给形参Point p,可是却并没有调用拷贝构造函数
*/调用拷贝构造函数
调用析构函数
调用析构函数

调用析构函数
调用析构函数


所以我想问一下,为什么会出现这种差异??

[解决办法]
据说编译器是会优化一些东西的
[解决办法]
把Point operator =(Point);
改成 Point& operator =(const & Point);
运行一下
[解决办法]
Point Point::operator =(Point p)
{
x = p.x;
y = p.y;
cout<<"重载赋值运算符函数"<<endl;
return (*this);
}

问题就在这个函数中,你出入实参的时候,编译器会创建一个临时变量的副本,会调用
你写的拷贝构造函数,所以会先 打印 调用拷贝构造函数
当函数返回(*this)的时候,也会创建一个临时的对象调用你的拷贝构造函数了

形参要尽量传引用或者指针,传对象的话会增加构造函数,析构函数开销,如果对象比较大的话还会占用内存开销
返回的时候一样,尽量返回引用或者指针
[解决办法]
Point func(Point p)
{
cout<<"已经进入到func( )的函数体内"<<endl;
Point temp(5, 5);
return temp;
}

你返回的是一个局部的对象,出函数的时候已经被析构了,所以临时对象调用的不是你写的拷贝构造函数
而是默认的拷贝构造函数

[解决办法]
编译器优化了

参考ISO/IEC 14882:2003(E)
12.8 Copying class objects
第15条款
[解决办法]
不知道你的什么编译器,我在V6和code::blocks10.05下都试过,全部是条用的赋值操作


[解决办法]
可能调用情况每个编译器会有不同吧。
拷贝构造和operator=,这样写效率高很多。
Point(const Point&);
Point& operator = (const Point&);

[解决办法]

探讨
不知道你的什么编译器,我在V6和code::blocks10.05下都试过,全部是条用的赋值操作

[解决办法]

我靠,你那比复制构造都用得值传递~
好了,这觉对是优化了,编译器对于临时变量的优化是很正常,更何况你这里简直是2次临时
[解决办法]
就算你自己写了析构函数,还是会再调用一遍自己默认的析构函数,另外我觉得楼主对于答非所问的网友有点不友好


探讨
引用:
Point func(Point p)
{
cout<<"已经进入到func( )的函数体内"<<endl;
Point temp(5, 5);
return temp;
}

你返回的是一个局部的对象,出函数的时候已经被析构了,所以临时对象调用的不是你写的拷贝构造函数
而是默认的拷贝构造函数


这位兄台,你老纠结在这个问题……

[解决办法]
C/C++ code
int main( ){    func(Point(Point(3,5)));    return 0;}
[解决办法]
就是和构造函数不同,编译器总是会为我们合成一个析构函数的,如果你自己写了析构函数,这个自动合成的析构函数就会调用你写的析构函数。:)

探讨
引用:

就算你自己写了析构函数,还是会再调用一遍自己默认的析构函数,另外我觉得楼主对于答非所问的网友有点不友好

你这句话是什么意思?什么叫做“还是会调用一遍自己默认的析构函数”?

[解决办法]
年轻人不要太气盛,大家都是互相切磋,共同进步,为何态度如此盛气凌人,何况是在提问,一点都不谦虚………

读书人网 >C++

热点推荐