C++中的临时对象temporary object

Thinking in C++ P368页关于Temporaries的论述中写道:But there is one thing about temporaries:they’re automatically const. Because you usually won’t be able to get your hands on a temporary object,telling it to do something that will change that temporary is almost certainly a mistake because you won’t be ableto use that information. By making all temporaries automatically const, the compiler informs you when you make that mistake.

意思是:temporary object自动具有const属性(后面所做实验证明这句话并不严谨,不过也可能是我对此句的理解有误)。因为通常你不能让一个temporary object去做一些会改变自己的事情,这是错误的,因为你根本就无法使用这些信息。通过让所有的temporaries 自动成为const,当你犯错时编译器会告知你。

但通过实验,正确的说法应该是:C++中对临时变量的引用必须进行const 引用。

临时变量:它在代码中看不到,但是确实存在。它就是临时对象---由编译器定义的一个没有命名的非堆对象。

临时变量产生的时机:

1. 函数调用类型转换

2.按值返回

如果一个参数是以一个非const引用传 入的,那么C++编译器就有理由相信我们传入的参数在函数中是可以被修改的,并且这个修改的变量在函数外也是可以使用的,但是如果我们把一个临时变量当成非const引用参数传进来,则由于临时变量的特殊性,对临时变量的修改在函数内部,而临时变量在使用完成后会释放,所以如果我们修改一个临时变量实际上没有意义的,因此C++编译器就加入了临时变量不能作为非const引用的这个语意限制,主要是限制这个非常规的用法的潜在错误。在编译期间就告诉你错误,比在运行时遇到问题要更为友好。

1.函数调用类型转换:

#include <iostream>
#include <string>
using namespace std;

void make_upper(string& s){}

int main(){
	string s1("hello, world");
	make_upper(s1);
	cout << s1 << endl;
	char text[] = "hello, world";
	//make_upper(text); error! convert char* to string
	cout << text << endl;
	return 0;
}

改为const引用后不报错。

2.函数返回值

#include <iostream>
#include <string>
using namespace std;

class X {};

X f() { return X(); }

void g1(X&) {}
void g2(const X&) {}

int main(){
	//g1(f());  error!
	g2(f());
	return 0;
}

但是临时变量具有const属性这一说法并不严谨,以下代码:

#include <iostream>
#include <string>
using namespace std;

class X {
	int i;
public:
	X (int ii = 100) : i(ii) {}
	void inc(){
		++i;
		cout << "Now i is " << i << endl;
	}
};

X f() { return X(); }

int main(){
	f().inc();
	return 0;
}

如果临时对象具有const属性,那么const对象不能调用非const成员函数,但是以上代码却能成功运行。

进一步的,可以将返回的对象赋给一个非常量对象,也可以对返回的对象进行赋值操作。

#include <iostream>
#include <string>
using namespace std;

class X {
	int i;
public:
	X (int ii = 100) : i(ii) { cout << "constructed addr is: " << this << endl; }
	X& operator=(const X o){
	    i = o.i;
	    cout << "assignment happened" << endl;
	    return *this;
	}
	void inc(){
		++i;
		cout << "Now i is " << i << endl;
	}
	~X(){
		cout << "deconstructed" << endl;
	}
};

X f() { return X(); }

int main(){
	f().inc();
	X a = f();
	cout << "a's addr is: " << &a << endl;
	a.inc();
	(f() = a).inc();
	return 0;
}

运行结果为:

可见,对于临时对象,若要对其进行引用,则只能进行const引用, 但作为普通对象时没有限制。
只有非常量的返回值(返回对象亦是返回值)才可以作为左值使用,若不想被用作左值,应该使用常量对象返回。
Only the non-const return value can be used as an lvalue.Thus, it's important to use const when returning an object by value if you want to prevent its use as an lvalue.       ——thinking in C++ 2nd Vol1 Chapter8.3 P367

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值