首页 > 代码库 > C++标准的规定:非常量的引用不能指向临时对象(转载)

C++标准的规定:非常量的引用不能指向临时对象(转载)

C++标准的规定:非常量的引用不能指向临时对象:

为了防止给常量或临时变量(只有瞬间的生命周期)赋值(易产生bug),只许使用const引用之。

下面的内容转自: http://blog.csdn.net/liuxialong/article/details/6539717

概括一下:

不能把临时对象作为实参传给非const引用。

例如:

void conv(string &str) { }int main() {    conv("dasd"); // 这里错了,编译器自动生成一个string(“dasd”)临时对象,不能将该临时对象传给非const引用}

因此,需要将其改为:

void conv(string str) { } // 值传递

或者

void conv(const string &str) { } // const引用,因为标准规定临时对象是不能更改的,所以要加上const修饰。

那么这里涉及到一个问题,什么时候会出现临时对象呢?

临时对象的定义:

来看一个例子,在c++里,这个tmp是局部对象(变量),而不是临时对象。

template <T>void swap(T &obj1, T &obj2) {    obj tmp=obj1; // 这里的tmp不能被称为临时对象,它只是局部对象    obj1=obj2;    obj2=tmp;}

在c++中,真正的临时对象是看不见的,它们不会出现在你的代码中。

建立一个没有命名的非堆(non-heap)对象会产生临时对象。

这种对象通常在两中条件下产生:为了使函数成功调用而进行隐式类型转换和函数返回对象时。

理解如何和为什么建立这些临时对象很重要,因为创建和释放它们的开销对于程序的性能来说有不可忽视的影响。

1, 首先考虑为使函数成功调用而建立临时对象这种情况。

当传送给函数的对象类型与参数类型不匹配会产生这种情况。

例如:文章开头的那个例子,conv函数的参数类型是string, 可是传入的实参却是const char *, 因此,编译器会自动进行隐式转换,

生成一个string("dasd")的临时对象,再把这个对象传入,这个没有命名的临时对象当然不能修改了,因此必须加上const修饰符。

这就是文章一开头的那个问题产生的原因。

2, 建立临时对象的第二种环境是函数返回对象时。

例如:operator+必须返回一个对象,以表示它的两个操作数的和(参见Effective C++ 条款23)。

operator+被这样声明:

template<typename T>T operator+(const T &lhs, const T &rhs);

这个函数的返回对象是临时的,因为它是没有被命名的,它只是函数的返回值。

你必须为每次调用operator+创建和释放这个对象付出代价。

关于临时对象的总结:

临时对象是有开销的,所以你应该尽可能的去除它们,然而更重要的是训练自己寻找可能建立临时对象的地方。

1, 在任何时候只要见到常量引用(reference to const)参数,就存在建立临时对象而绑定在参数上的可能性。

2, 在任何时候只要见到返回对象,就会有一个临时对象被建立(以后被释放)。

学会寻找这些对象构造,你就能显著的增强透过编译器表面动作而看到哦啊其背后开销的能力