关于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个在函数调用结束不会被释放的对象的引用。比如外部传入的对象,比如函数所属类的成员变量等。