#include <iostream>
using namespace std;
class ra{
public:
ra(int temp = 0);
ra(const ra& c);
friend const ra operator*(const ra& c, const ra& d);
//~ra() { cout<<"destructor"<<endl;}
private:
int a;
};
ra::ra(int temp)
{
a = temp;
cout<<"constructor() "<<a<<endl;
}
ra::ra(const ra& c)
{
a = c.a;
cout<<"copy constructor() "<<a<<endl;
}
const ra operator*(const ra& c,const ra& d)
{
return ra(c.a*d.a);
}
void main()
{
ra c(5);
ra d(6);
ra e = c*d;
return;
}
当没有析构函数时候,输出结果为:
constructor() 5
constructor() 6
constructor() 30
copy constructor() 30
copy constructor() 30
当有析构函数的时候,输出结果为:
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
各位大虾帮帮忙解释为什么会有这种现象?
12 个解决方案
#1
正常现象啊,注意 c*d会产生临时变量的
#2
其实不是正常现象,LZ可以尝试在不同的编译器上做下实验,
#3
当没有析构函数时候,输出结果为:
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
#4
当有析构函数的时候,输出结果为:
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
////////////////////////////////
上面的结果可能是编译器总是造成的。
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
////////////////////////////////
上面的结果可能是编译器总是造成的。
#5
在 vs2005 中:
无析构的结果:
constructor() 5
constructor() 6
constructor() 30
有析构的结果:
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
无析构的结果:
constructor() 5
constructor() 6
constructor() 30
有析构的结果:
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
#6
[size=11px]疑问在于:
为什么自己写了析构函数,本该有的调用拷贝构造函数的地方却没有调用呢???
用默认的析构函数才有调用拷贝构造函数呢??[/size]
to lihao21:
你的解释是不对的
当没有析构函数时候,输出结果为:
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
????????????这里编译器会执行。。。返回值优化。。。,不会再调用拷贝构造函数了,再执行 ra(c.a*d.a)时就直接把对象创建在外部返回值的内存单元。
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
为什么自己写了析构函数,本该有的调用拷贝构造函数的地方却没有调用呢???
用默认的析构函数才有调用拷贝构造函数呢??[/size]
to lihao21:
你的解释是不对的
当没有析构函数时候,输出结果为:
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
????????????这里编译器会执行。。。返回值优化。。。,不会再调用拷贝构造函数了,再执行 ra(c.a*d.a)时就直接把对象创建在外部返回值的内存单元。
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
#7
没有调用copy constructor的原因确实是返回值优化.
而destructor被一些编译器用作是否执行返回值优化的标志.如果用户定义了destructor,编译器会认为copy constructor的代价太高(定义destructor一般是为了解决资源的释放问题,那么copy constructor必然需要分配资源),从而执行返回值优化.
当然,这依赖于编译器的策略,各编译器行为可以不一样.
而destructor被一些编译器用作是否执行返回值优化的标志.如果用户定义了destructor,编译器会认为copy constructor的代价太高(定义destructor一般是为了解决资源的释放问题,那么copy constructor必然需要分配资源),从而执行返回值优化.
当然,这依赖于编译器的策略,各编译器行为可以不一样.
#8
你没有重载 void operator = (ra& a);函数.return ra(c.a*d.a); 实际上系统会实例化一个隐含的实例,而且调试也追踪不到.
#9
楼主用的VC2046吧 我在VC6 2003下试都没有这个结果
copy constructor() 30
copy constructor() 30
copy constructor() 30
copy constructor() 30
#10
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
????????????这里编译器会执行。。。返回值优化。。。,不会再调用拷贝构造函数了,再执行 ra(c.a*d.a)时就直接把对象创建在外部返回值的内存单元。
************************************************
那为何会在这里调用copy constructor??
????????????这里编译器会执行。。。返回值优化。。。,不会再调用拷贝构造函数了,再执行 ra(c.a*d.a)时就直接把对象创建在外部返回值的内存单元。
************************************************
那为何会在这里调用copy constructor??
#11
编译器优化?
#12
lihao21::
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
关于第一个拷贝构造函数的调用我没理解啊。如果按你说的生成一个临时对象的话,应该调用的是构造函数啊。怎么会是拷贝构造函数呢?
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
关于第一个拷贝构造函数的调用我没理解啊。如果按你说的生成一个临时对象的话,应该调用的是构造函数啊。怎么会是拷贝构造函数呢?
#1
正常现象啊,注意 c*d会产生临时变量的
#2
其实不是正常现象,LZ可以尝试在不同的编译器上做下实验,
#3
当没有析构函数时候,输出结果为:
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
#4
当有析构函数的时候,输出结果为:
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
////////////////////////////////
上面的结果可能是编译器总是造成的。
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
////////////////////////////////
上面的结果可能是编译器总是造成的。
#5
在 vs2005 中:
无析构的结果:
constructor() 5
constructor() 6
constructor() 30
有析构的结果:
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
无析构的结果:
constructor() 5
constructor() 6
constructor() 30
有析构的结果:
constructor() 5
constructor() 6
constructor() 30
destructor
destructor
destructor
#6
[size=11px]疑问在于:
为什么自己写了析构函数,本该有的调用拷贝构造函数的地方却没有调用呢???
用默认的析构函数才有调用拷贝构造函数呢??[/size]
to lihao21:
你的解释是不对的
当没有析构函数时候,输出结果为:
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
????????????这里编译器会执行。。。返回值优化。。。,不会再调用拷贝构造函数了,再执行 ra(c.a*d.a)时就直接把对象创建在外部返回值的内存单元。
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
为什么自己写了析构函数,本该有的调用拷贝构造函数的地方却没有调用呢???
用默认的析构函数才有调用拷贝构造函数呢??[/size]
to lihao21:
你的解释是不对的
当没有析构函数时候,输出结果为:
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
????????????这里编译器会执行。。。返回值优化。。。,不会再调用拷贝构造函数了,再执行 ra(c.a*d.a)时就直接把对象创建在外部返回值的内存单元。
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
#7
没有调用copy constructor的原因确实是返回值优化.
而destructor被一些编译器用作是否执行返回值优化的标志.如果用户定义了destructor,编译器会认为copy constructor的代价太高(定义destructor一般是为了解决资源的释放问题,那么copy constructor必然需要分配资源),从而执行返回值优化.
当然,这依赖于编译器的策略,各编译器行为可以不一样.
而destructor被一些编译器用作是否执行返回值优化的标志.如果用户定义了destructor,编译器会认为copy constructor的代价太高(定义destructor一般是为了解决资源的释放问题,那么copy constructor必然需要分配资源),从而执行返回值优化.
当然,这依赖于编译器的策略,各编译器行为可以不一样.
#8
你没有重载 void operator = (ra& a);函数.return ra(c.a*d.a); 实际上系统会实例化一个隐含的实例,而且调试也追踪不到.
#9
楼主用的VC2046吧 我在VC6 2003下试都没有这个结果
copy constructor() 30
copy constructor() 30
copy constructor() 30
copy constructor() 30
#10
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
????????????这里编译器会执行。。。返回值优化。。。,不会再调用拷贝构造函数了,再执行 ra(c.a*d.a)时就直接把对象创建在外部返回值的内存单元。
************************************************
那为何会在这里调用copy constructor??
????????????这里编译器会执行。。。返回值优化。。。,不会再调用拷贝构造函数了,再执行 ra(c.a*d.a)时就直接把对象创建在外部返回值的内存单元。
************************************************
那为何会在这里调用copy constructor??
#11
编译器优化?
#12
lihao21::
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
关于第一个拷贝构造函数的调用我没理解啊。如果按你说的生成一个临时对象的话,应该调用的是构造函数啊。怎么会是拷贝构造函数呢?
constructor() 5 //ra c(5); 构造了一个对象
constructor() 6 //ra d(6); 构造了一个对象
constructor() 30 //return ra(c.a*d.a); 也生成一个对象。
copy constructor() 30 //由于const ra返回的不是一个引用,故生成临时对象,调用Copy构造函数
copy constructor() 30 //ra e = c*d; 再次调用Copy构造函数
关于第一个拷贝构造函数的调用我没理解啊。如果按你说的生成一个临时对象的话,应该调用的是构造函数啊。怎么会是拷贝构造函数呢?