轉(zhuǎn)載
有言在先: 返回局部對(duì)象和引用, 就像返回局部變量的地址一樣, 非常非常危險(xiǎn), 要避免使用。 下面程序中有的地方返回了局部對(duì)象的指針, 實(shí)際上也是危險(xiǎn)的, 但本文先不討論這個(gè)。
先來看一個(gè)入門級(jí)的程序:
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A constructor" << endl;
}
};
void fun(A a)
{
}
int main()
{
A a;
cout << "---" << endl;
fun(a);
return 0;
}
結(jié)果為:
A constructor
---
編譯器自動(dòng)產(chǎn)生的拷貝構(gòu)造函數(shù)得到了調(diào)用。
#include <iostream>
using namespace std;
class A
{
public:
~A()
{
cout << "A deconstructor" << endl;
}
};
void fun(A a)
{
}
int main()
{
A a;
cout << "---" << endl;
fun(a);
return 0;
}
結(jié)果為:
---
A deconstructor
A deconstructor
注意, 有兩個(gè)對(duì)象, 所以有兩次析構(gòu)。
在第一個(gè)程序中, 我們來顯式定義一下拷貝構(gòu)造函數(shù):
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A constructor" << endl;
}
A(A& a)
{
cout << "copy constructor" << endl;
}
};
void fun(A a)
{
}
int main()
{
A a;
cout << "---" << endl;
fun(a);
return 0;
}
結(jié)果為:
A constructor
---
copy constructor
可見, 拷貝構(gòu)造函數(shù)確實(shí)被調(diào)用了
我們來繼續(xù)看:
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A constructor" << endl;
}
A(A& a)
{
cout << "copy constructor" << endl;
}
~A()
{
cout << "A deconstructor" << endl;
}
};
void fun(A &a)
{
}
int main()
{
A a;
cout << "---" << endl;
fun(a);
return 0;
}
結(jié)果為:
A constructor
---
A deconstructor
可見, 沒有對(duì)象的拷貝。 這樣, 在fun函數(shù)中, 就省略了拷貝的過程, 而是直接引用a. 節(jié)省時(shí)間, 節(jié)省空間, 真好
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A constructor" << endl;
}
A(A& a)
{
cout << "copy constructor" << endl;
}
~A()
{
cout << "A deconstructor" << endl;
}
};
A fun()
{
A a;
cout << "------" << endl;
return a;
}
int main()
{
A a;
cout << "---" << endl;
fun();
return 0;
}
結(jié)果為:
A constructor
---
A constructor
------
copy constructor
A deconstructor
A deconstructor
A deconstructor
繼續(xù)看:
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A constructor" << endl;
}
A(A& a)
{
cout << "copy constructor" << endl;
}
~A()
{
cout << "A deconstructor" << endl;
}
};
A& fun()
{
A a;
cout << "------" << endl;
return a; // 翻譯局部對(duì)象的引用, 危險(xiǎn)。
}
int main()
{
A a;
cout << "---" << endl;
fun();
return 0;
}
結(jié)果為:
A constructor
---
A constructor
------
A deconstructor
A deconstructor
看吧, 在函數(shù)返回的時(shí)候, 是返回引用的, 這樣, 又少了一次拷貝。
繼續(xù)看一個(gè)稍微復(fù)雜一點(diǎn)的:
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A constructor" << endl;
}
A(A& a)
{
cout << "copy constructor" << endl;
}
~A()
{
cout << "A deconstructor" << endl;
}
};
A fun(A a)
{
A aa;
cout << "------" << endl;
return aa;
}
int main()
{
A a;
cout << "---" << endl;
fun(a);
return 0;
}
結(jié)果:
A constructor
---
copy constructor
A constructor
------
copy constructor
A deconstructor
A deconstructor
A deconstructor
A deconstructor
對(duì)上面程序進(jìn)行優(yōu)化:
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A constructor" << endl;
}
A(A& a)
{
cout << "copy constructor" << endl;
}
~A()
{
cout << "A deconstructor" << endl;
}
};
A& fun(A& a)
{
A aa;
cout << "------" << endl;
return aa; // 返回局部對(duì)象的引用, 危險(xiǎn)。
}
int main()
{
A a;
cout << "---" << endl;
fun(a);
return 0;
}
結(jié)果為:
A constructor
---
A constructor
------
A deconstructor
A deconstructor
可見, 對(duì)象引用在C++中確實(shí)有很大的好處。比傳對(duì)象快捷高效, 比指針更優(yōu)美。