Test Header HTML Code

关于C++返回引用的问题

Effective C++ 条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用

这里可以分为2部分:

1,局部对象:因为返回之后该局部对象已经被释放了。

2内部new的对象:不能让外部通过引用来释放这里new的对象,别人会很纳闷,故会泄漏内存。

这里我要对1进行一下分析:

1 #include <iostream>
2
3 class A
4 {
5 friend std::ostream& operator<<(std::ostream& out, const A &a);
6 public:
7 A(int i) : m_x(i){}
A(const A&a) : m_x(a.m_x) { std:: cout << "copy A(" << m_x << ")" << std ::endl;}
8 ~A() { std::cout << "~A()" << std::endl; }
9 private:
10 int m_x;
11 };
12
13 class B
14 {
15 public:
16 B() : m_a(9) {}
17 const A& getA() { return m_a; }
18
19 private:
20 A m_a;
21 };
22
23 std::ostream& operator<<(std::ostream& out, const A &a)
-24 {
25 out << a.m_x;
26 return out;
27 }
28
29 const A & f(int i) { return A(i); }
30
31 int main()
32 {
33 A a = f(2);
34 B b;
35 std::cout << "1:" << f(1) << std::endl;
36 std::cout << "2:" << a << std::endl;
37 std::cout << "3:" << b.getA() << std::endl;
38 return 0;
39 }

编译警告:

test.cpp: In function ‘const A& f(int)’:

test.cpp:29: warning: returning reference to temporary

告诉我们不能返回1个临时变量的引用。

注意B::getA()编译没有警告,因为其返回的引用为成员对象,外部在调用该方法getA()时,可以保证B::m_a没有释放,是有效内存。

而调用f(int i)时,会先释放,我们可以看到第1条打印语句,先输出了~A(),再输出 1:-1077671300。有人也许会想为什么不是 1:~A() -1077671300,这是因为计算运算结果的时候先从右边的算起了。

由于临时变量已经释放,其返回的引用为无效地址,所以取的值也就错误了。

而打印第2条,我们发现A a = f(2)中返回给a的对象是正常的,也就是说a的拷贝构造函数的参数是一个有效的引用,我认为这里是编译器做了优化,否则很难解释析构函数和拷贝构造函数的调用顺序。

输出结果:

~A()

copy A(2)

~A()

1:-1080612004

2:2

3:9

~A()

~A()

综上所述:

在1个函数中,我们可以返回1个在函数调用结束不会被释放的对象的引用。比如外部传入的对象,比如函数所属类的成员变量等。

posted on 2011-03-19 11:44  宁静的水泡  阅读(4572)  评论(0编辑  收藏  举报

导航

Test Rooter HTML Code