千家信息网

c++临时对象是什么

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容介绍了"c++临时对象是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是临时对象?C
千家信息网最后更新 2026年11月02日c++临时对象是什么

本篇内容介绍了"c++临时对象是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

什么是临时对象?

C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象.

通常出现在以下两种情况:

(1)为了使函数调用成功而进行隐式类型转换的时候。

传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁。如下例:

//计算字符ch在字符串str中出现的次数 int countChar (const string& str, char ch); char buffer[]; char c; //调用上面的函数 countChar (buffer, c);

我们看的第一个参数为char[],而函数的参数类型为const string&,参数不一致,看看能否进行隐式转化,string类有个构造函数是可以作为隐式转化函数(参见5)的。那么编译器会产生一个 string的临时变量,以buffer为参数进行构造,那么countChar中的str参数会绑定到此临时变量上,直到函数返回时销毁。

注意这样的转化只会出现在两种情况下:函数参数以传值(by value)的方式传递 或者 对象被传递到一个 reference-to-const 参数上。

传值方式:

int countChar (string str, char ch); string buffer; char c; //参数通过传值方式传递 countChar (buffer, c);

这种方法会调用string的拷贝构造函数生成一个临时变量,再将这个临时变量绑定到str上,函数返回时进行销毁。

传常量引用:

开始的实例即时属于这种情况,但一定强调的是传递的是const型引用,如将开始函数的原型改为

int countChar (string& str, char ch);

下面调用相同,编译器会报错!为什么C++设计时要求当对象传递给一个reference-to-non-const 参数不会发生隐式类型转化呢?

下面的实例可能向你说明这样设计的目的:

//声明一个将str中字符全部转化为大写 void toUpper (string& str); char buffer[] = "hazirguo"; toUpper(buffer);                 //error!!非const引用传递参数不能完成隐式转化

如果编译器允许上面的传递完成,那么,会生成一个临时对象,toUpper函数将临时变量的字符转化为大写,返回是销毁对象,但是对buffer内容毫无影响!程序设计的目地是期望对"非临时对象"进行修改,而如果对reference-to-non-cosnt对象进行转化,函数只会对临时变量进行修 改。这就是为什么C++中要禁止non-const-reference参数产生临时变量的原因了。

(2)当函数返回对象的时候。

当函数返回一个对象时,编译器会生成一个临时对象返回,如声明一个函数用来合并两个字符串:

const string strMerge (const string s1, const string s2);
大多时候是无法避免这样的临时变量产生的,但是现代编译器可以将这样的临时变量进行优化掉,这样的优化策略中,有个所谓的"返回值优化",下一篇具体讲解。
 总结:
临时对象有构造和析构的成本,影响程序的效率,因此尽可能地消除它们。而更为重要的是很快地发现什么地方会生成临时对象:
  • 当我们看到一个reference-to-const参数时,极可能一个临时对象绑定到该参数上;

  • 当我们看到函数返回一个对象时,就会产生临时对象。

参考:http://www.cnblogs.com/hazir/archive/2012/04/18/2456144.html

C++中的返回值优化(return value optimization)

返回值优化(Return Value Optimization,简称RVO),是这么一种优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消 耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。而如果稍微做一点优化,就可以将成本降低到一个构造函数的代价,下面是 在Visual Studio 2008的Debug模式下做的一个测试:(在GCC下测试的时候可能编译器自己进行了RVO优化,看不到两种代码的区别)

// C++ Return Value Optimization
// 作者:代码疯子
// 博客: http://www.programlife.net/
#include
using namespace std;
class Rational
{
public:
Rational( int numerator = 0, int denominator = 1) : n(numerator), d(denominator) {
cout << " Constructor Called... " << endl;
}
~Rational() {
cout << " Destructor Called... " << endl;
}
Rational( const Rational& rhs) {
this->d = rhs.d;
this->n = rhs.n;
cout << " Copy Constructor Called... " << endl;
}
int numerator() const { return n; }
int denominator() const { return d; }
private:
int n, d;
};
const Rational operator*( const Rational& lhs, const Rational& rhs) {
cout << " ----------- Enter operator* ----------- " << endl;
Rational tmp(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
cout << " ----------- Leave operator* ----------- " << endl;
return tmp;
}
int main( int argc, char **argv) {
Rational x( 1, 5), y( 2, 9);
Rational z = x * y;
cout << " calc result: " << z.numerator()
<< " / " << z.denominator() << endl;

return 0;
}

复制代码

函数输出截图如下:

可以看到消耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。

而如果把operator*换成另一种形式:

const Rational operator*( const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}

就只会消耗一个构造函数的成本了:

参考: http://www.programlife.net/cpp-return-value-optimization.html

返回值优化(RVO)与具命返回值优化(NRVO)

这是一项编译器做的优化,已经是一种很常见的优化手段了,搜一下可以找到很多的资料,在MSDN 里也有相关的说明。

返回值优化,顾名思义,就是与返回值有关的优化,是当函数是按值返回(而不是引用、指针)时,为了避免产生不必要的临时对象以及值拷贝而进行的优化。

先看看下面的代码:

typedef unsigned int UINT32;
class MyCla
{
public:
MyCla(UINT32 a_size = 10):size(a_size) {
p = new UINT32[size];
}
MyCla(MyCla const & a_right):size(a_right.size) {
p = new UINT32[size];
memcpy(p, a_right.p, size* sizeof(UINT32));
}
MyCla const& operator = (MyCla const & a_right) {
size = a_right.size;
p = new UINT32[size];
memcpy(p, a_right.p, size* sizeof(UINT32));
return * this;
}
~MyCla() {
delete [] p;
}
private:
UINT32 *p;
UINT32 size;
};
MyCla TestFun() {
return MyCla();
}
int _tmain( int argc, _TCHAR* argv[])
{
MyCla a = TestFun();
return 0;
}

复制代码

TestFun() 函数返回了一个 MyCla 对象,而且是按值传递的。

在没有任何"优化"之前,这段代码的行为也许是这样的:return MyCla() 这行代码中,构造了一个 MyCla 类的临时的无名对象(姑且叫它t1),接着把 t1 拷贝到另一块临时对象 t2(不在栈上),然后函数保存好 t2 的地址(放在 eax 寄存器中)后返回,TestFun 的栈区间被"撤消"(这时 t1 也就"没有"了,t1 的生存域在 TestFun 中,所以被析构了),在 MyCla a = TestFun(); 这一句中,a 利用 t2 的地址,可以找到 t2 进行,接着进行构造。这样 a 的构造过程就完成了。然后再把 t2 也"干掉"。

可以看到, 在这个过程中,t1 和 t2 这两个临时的对象的存在实在是很浪费的,占用空间不说,关键是他们都只是为a的构造而存在,a构造完了之后生命也就终结了。既然这两个临时的对象对于程序 员来说根本就"看不到、摸不着"(匿名对象),于是编译器干脆在里面做点手脚,不生成它们!怎么做呢?很简单,编译器"偷偷地"在我们写的TestFun 函数中增加一个参数 MyCla&,然后把 a 的地址传进去(注意,这个时候 a 的内存空间已经存在了,但对象还没有被"构造",也就是构造函数还没有被调用),然后在函数体内部,直接用a来代替原来的"匿名对象",在函数体内部就完 成a的构造。这样,就省下了两个临时变量的开销。这就是所谓的"返回值优化"!在 VC7 里,按值返回匿名对象时,默认都是这么做。

上 面说的是"返回值优化(RVO)",还有一种"具名返回值优化(NRVO)",是对于按值返回"具名对象"(就是有名字的变量!)时的优化手段,其实道理 是一样的,但由于返回的值是具名变量,情况会复杂很多,所以,能执行优化的条件更苛刻,在下面三种情况下(来自 MSDN),NRVO 将一定不起作用:

  1. 不同的返回路径上返回不同名的对象(比如if XXX 的时候返回x,else的时候返回y)

  2. 引入 EH 状态的多个返回路径(就算所有的路径上返回的都是同一个具名对象)

  3. 在内联asm语句中引用了返回的对象名。

不过就算 NRVO 不能进行,在上面的描述中的 t2 这个临时变量也不会产生,对于 VC 的 C++ 编译器来说,只要你写的程序是把对象按值返回的,它会有两种做法,来避免 t2 的产生。拿下面这个程序来说明:

MyCla TestFun2() {
MyCla x( 3);
return x;
}

一种做法是像 RVO一样,把作为表达式中获取返回值来进行构造的变量 a 当成一个引用参数传入函数中,然后在返回语句之前,用要返回的那个变量来拷贝构造 a,然后再把这个变量析构,函数返回原调用点,a 就构造好了。

还有一种方式, 是在函数返回的时候,不析构x,而直接把x的地址放到 exa 寄存器中,返回调到 TestFun2 的调用点上,这时,a 可以用 exa 中存着的地址来进行构造,a 构造完成之后,再析构原来的变量 x !是的,注意到其实这时,x 的生存域已经超出了TestFun2,但由于这里x所在TestFun2的栈虽然已经无效,但是并没有谁去擦写这块存,所以x其实还是有效的,当然,一切 都在汇编的层面,对于C++语言层面来讲是透明的。

"c++临时对象是什么"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

对象 函数 变量 参数 编译器 编译 时候 生成 情况 程序 C++ 代码 地址 字符 类型 面的 两个 就是 拷贝 方式 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 华服互联网科技靠谱吗 北京路客互联网科技有限公司 互联网科技深圳 百单互联网科技有限公司 米客互联网科技 狮子座互联网科技培训 天扬科技互联网广告 汉立互联网科技有限公司联系电话 现代科技和互联网有关系吗 中盈科技互联网信息有限公司 青海科技产业互联网发展 中和天地互联网科技有限公司 恒生互联网科技业指数调整周期 互联网金融科技公司的优势 中天科技中国工业互联网 半导体行业属于互联网高科技类吗 郑州欣桑互联网科技有限公司 抖集互联网科技技术咨询 优雇互联网科技有限公司 互联网科技快速发展优美句子 广州百单互联网科技有限公司 互联网 科技创业 互联网与未来科技 互联网金融科技委员会 互联网科技有限公司 翻译 湖南洣水互联网科技有限公司扣款 阿里互联网科技公司 贵州叶脉互联网科技有限公司所属行业 迪庆互联网科技招生 上海京穆互联网科技有限公司
0