关于const引用做为形参的疑惑。

GeminiXXXCC 2005-06-29 07:51:29
当函数形参是一个const引用的时候,是否产生临时对象?
double a = 1.34 ;
const int &b = a ;
const int &c = 1024 ;
在上面的const引用中都产生了临时变量,然后引用变量指向该临时变量。
在函数传递中,比如:
class X {};
X f() { return X(); }
void g1(X&) {}
void g2(const X&) {}
int main() {
g1(f()) ;
g2(f());
return 0;
}
因为在f()函数返回的是一个临时变量,因此f()函数结束的时候这个临时变量的生命期也应该
结束了。因此g1的调用是非法的,至于g2则因为是const引用,所以产生了另一个临时变量。
g2的调用是可以的。
那么我现在的疑问是,如果传给g2的是一个正常的对象,会产生临时变量吗?难道只有在传递的
对象是常量,或者临时变量的时候const引用才自动的产生另一个临时变量?
如果不管传递的是什么对象,const引用都会产生临时变量,那么和值传递应该没有什么区别了,
都应该需要一个临时对象的构造拷贝析构过程,也就没有了快速的优点。
事实到底是怎么样子的?
...全文
500 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
xlsue 2005-06-30
  • 打赏
  • 举报
回复
如果你的编译器符合C++标准,f()是不会产生临时变量的.可以被优化掉.
C++真正的所谓的临时对象是不可见的,也就是所说的无具名对象.产生临时对象有2中情况:
1.隐式型别转换
2.函数返回对象
C++禁止non-const-reference参数产生临时对象.任何时候看见一个referenct-to-const参数,就可能有一个临时对象产生.
具体看:More Effective C++条款19\20
JohnTitor 2005-06-29
  • 打赏
  • 举报
回复
这个程序只产生了一个临时变量产生时间是f()return的时候,结束是g2()结束的时候?
---------------
是的
GeminiXXXCC 2005-06-29
  • 打赏
  • 举报
回复
楼上的强,果然在g2过后,调用了~X()。
那么这个程序只产生了一个临时变量产生时间是f()return的时候,结束是g2()结束的时候?
defyer007 2005-06-29
  • 打赏
  • 举报
回复
同意楼上的
和编译器有关
defyer007 2005-06-29
  • 打赏
  • 举报
回复
const引用形参 不会产生临时变量
你可以在g1()和g2()中分别修改传入的形参,然后看其值是否有改变
yhbttfile 2005-06-29
  • 打赏
  • 举报
回复
你提到的临时变量是不会导致内存泄漏。
存在泄漏一般指通过动态申请(new/malloc/remalloc等操作)的内存没有释放。

你的代码:
1 int main() {
2 g2(f());
3 return 0;
4 }

上面的第二行中产生的临时对象,在g2调用完成以后,就已经释放了(因为临时对象都是在堆栈上分配的)。
不过,有些编译器由于设计原因,没有做到语句执行完成后就马上弹出堆栈中的临时对象,而是遇到一个“}”才触发这个弹出动作。

JohnTitor 2005-06-29
  • 打赏
  • 举报
回复
f()返回的临时对象在g2函数结束后就马上析构了,因为这个临时变量只是g2函数的局部变量。
在g2(f())过后,x指向的对象就已经析构,x->n的值就无法预测了
GeminiXXXCC 2005-06-29
  • 打赏
  • 举报
回复
不过还有一个问题,
#include <iostream>
using namespace std ;

class X {public:int n ;X() {n=10 ;} ;};
const X *x ;
X f() { return X(); }
void g2(const X& a) {x = &a ;}
int main() {
g2(f());
return 0;
}
也就是说把f()返回的临时对象的地址用一个全局变量保存起来,程序比较大,运行若干时间后,这个临时变量占用的内存是否会释放,如果释放了,那么这个时候x->n的值也许会被改变吧?
GeminiXXXCC 2005-06-29
  • 打赏
  • 举报
回复
OK,明白了。
除非是传递常量,否则const引用是不会产生临时变量的。
JohnTitor 2005-06-29
  • 打赏
  • 举报
回复
因为在f()函数返回的是一个临时变量,因此f()函数结束的时候这个临时变量的生命期也应该
结束了。因此g1的调用是非法的,至于g2则因为是const引用,所以产生了另一个临时变量。
g2的调用是可以的
----------------------------------------------
不是因为g2的参数是const引用才产生另外一个临时变量,事实上如果不考虑编译优化的话,那么
g1(f())和g2(f())这两个调用中,编译器都为f()的返回值生成临时变量,g1(f())之所以非法是因为编译器不允许对临时变量的引用是非const的
JohnTitor 2005-06-29
  • 打赏
  • 举报
回复
如果传给g2的是一个正常的对象,会产生临时变量吗?
-------------------
不会。

是否产生临时变量跟const无关,
事实上是在编译器产生了临时变量之后,才检查对这个临时变量的引用是否为const
如果编译器发现这个引用不是const的话,那么就报错。

也就是说临时变量是编译器根据需要而产生的,产生了之后要求对这个临时变量的引用必须为const
qfeng_zhao 2005-06-29
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

class PP
{
public:
PP() { x = 0; count++;}
PP(int _x) : x(_x) {count++;}

static int count;
int x;
};

int PP::count = 0;
void fun(const PP &p)
{
cout << " p in fun is " << p.x << endl;
}

void main()
{
PP p;
const PP x(10);
fun(p);
fun(x);
cout << " p in fun is " << p.x << endl;

cout << p.count << endl;
}

输出count为2,也就是说无论传进的对象是否const,都没有创建新的对象
GeminiXXXCC 2005-06-29
  • 打赏
  • 举报
回复
如果是X temp;
g2(temp)呢,也不会产生临时对象了?
也就是说const引用可以根据需要来决定是否产生临时对象?
qfeng_zhao 2005-06-29
  • 打赏
  • 举报
回复
const X temp;
g2(temp);
就不会产生临时变量了,这样既能按引用传递参数,有不至于在程序中改变传进来的参数的值
xlsue 2005-06-29
  • 打赏
  • 举报
回复
类型不匹配,才产生的啊.你要理解临时变量在什么时候产生

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧