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, 在任何时候只要见到返回对象,就会有一个临时对象被建立(以后被释放)。

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

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

时间: 2024-12-22 12:10:58

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

非const引用不能指向临时变量

没找到具体原因,MSDN看到下面这句,VC是从2008才有这一限制的,感觉就是从语法上对临时变量增加了限定,因为一般说来修改一个临时变量是毫无意义的,通过增加限定,强调临时变量只读语义.虽然实际上修改临时变量并不会有问题. Visual Studio 2008 In previous releases of Visual C++, non-const references could be bound to temporary objects. Now, temporary objects ca

为什么父类引用可以指向子类对象 子类引用不能指向父类对象 泛型

假设有父类Fu ,其子类为Zi ,从对象的内存角度,假设Fu类里面的变量占内存2M, Zi 类里的变量占内存1M: Fu f = new Fu ();//系统将分配2M内存 Zi z = new Zi ();//系统将分配3M内存(2+1) 因为子类中有一个隐藏的引用super会指向父类实例,所以在实例化子类之前会先实例化一个父类,也就是说会先执行父类的构造函数.所以z可以调用父类的方法. Zi z1= z; //z1指向那3M的内存. Fu f1 = (Fu)z;//这时f1会指向那3M内存中

[转载]非常量引用的初始值必须为左值的问题

首先,先看下面一个例子: eg.1 #include<</span>iostream> usingnamespace std; int main(){ int i =2; double &r =i; return 0; } gcc error: invalid initialization of reference of type 'double&' from expression of type 'int' 如果改成 const double &r =i;

【转】int &amp;&amp; 非常量右值

C++ 11中引入的右值引用正好可用于标识一个非常量右值.C++ 11中用&表示左值引用,用&&表示右值引用,如: int &&a = 10 右值引用根据其修饰符的不同,也可以分为非常量右值引用和常量右值引用. C++ 11中引入的一个非常重要的概念就是右值引用.理解右值引用是学习“移动语义”(move semantics)的基础.而要理解右值引用,就必须先区分左值与右值. 对左值和右值的一个最常见的误解是:等号左边的就是左值,等号右边的就是右值.左值和右值都是针对

临时变量作为非const的引用进行参数传递引发的编译错误

1.错误原因即解决办法 Linux环境运行,使用g++编译,观察如下代码,会出现: invalid initialization of non-const reference of type 'std::string&' from a temporary of type 'std::string'的错误. 其中文意思为临时变量无法为非const的引用初始化.也就是在参数传递的过程中,出现错误.出错的代码如下: void print(string& str) { cout<<st

父类指针可以直接指向子类对象,父类引用可以直接引用子类对象

1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class parent{ 5 public: 6 int mi; 7 void add(int v){ 8 mi += v; 9 } 10 void add(int a,int b){ 11 mi += (a+b); 12 } 13 }; 14 class child:public parent{ 15 public: 16 int mv; 17 vo

c++中临时变量不能作为非const的引用参数

试看下面的代码: #include <iostream> using namespace std; void f(int &a) { cout << "f(" << a  << ") is being called" << endl; } void g(const int &a) { cout << "g(" << a << "

对常量的引用(reference to const)的一般用途(转载)

如果是对一个常量进行引用,则编译器首先建立一个临时变量,然后将该常量的值置入临时变量中,对该引用的操作就是对该临时变量的操作.对C++常量引用可以用其它任何引用来初始化:但不能改变. 关于引用的初始化有两点值得注意: (1)当初始化值是一个左值(可以取得地址)时,没有任何问题: (2)当初始化值不是一个左值时,则只能对一个const T&(常量引用)赋值.而且这个赋值是有一个过程的: 首先将值隐式转换到类型T,然后将这个转换结果存放在一个临时对象里,最后用这个临时对象来初始化这个引用变量. 通过

错误: ISO C++ 不允许在类内初始化非常量静态成员

错误: ISO C++ 不允许在类内初始化非常量静态成员 今天开始学C++ primer,在牵扯到Sales_item.h头文件时,出现了一些问题(和C++11新特性相关),当前的编译器版本是gcc/g++ 4.6.3,所以需要升级.可以利用PPA升级到4.8.1,如下: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update; sudo apt-get install gcc-4.8 g++-4.8 sud