本篇首先小结类中动态内存的使用,然后记录返回对象。
new
分配动态内存,则析构函数中必须使用delete
释放动态内存。new
与new []
的兼容性。函数除了返回普通对象以外,还可以返回对象的引用(或指针),const对象,const引用对象或指针。
上篇提到,函数返回对象会调用复制构造函数(编译器关闭RVO),增加了程序运行时间和内存使用。
返回const类型的目的在于,const常量不会被修改。
返回对象的引用(指针)的好处是,不会调用复制构造函数。
注意:返回的引用必须是在函数结束后仍然存在的对象。在函数中创建的局部对象不能通过引用和指针返回。
返回const引用,一方面可以防止函数调用语句被赋值,另一方面如果要返回传入的const引用,则返回类型必须是const引用。
#include <cstdio> #include <iostream> #include <cstring> using std::ostream; class A{ private: int a_; int b_; int c_; public: A(); A(int, int, int); A operator- (const A&) const; const A operator+ (const A&) const; const A& operator= (const A&); friend ostream& operator<< (ostream& os, const A&); }; A::A(): a_(0), b_(0), c_(0) {} A::A(int a, int b, int c): a_(a), b_(b), c_(c) {} A A::operator- (const A& s) const{ int a = a_ - s.a_; int b = b_ - s.b_; int c = c_ - s.c_; return A(a, b, c); } const A A::operator+ (const A& s) const{ int a = a_ + s.a_; int b = b_ + s.b_; int c = c_ + s.c_; return A(a, b, c); } ostream& operator<< (ostream& os, const A& s){ os << s.a_ << " " << s.b_ << " " << s.c_ << '\n'; return os; } const A& A::operator= (const A& s){ return s; } const A func(const A& s){ return s; } const A& funcc(const A& s){ return s; } int main(){ A s1(1, 1, 1); A s2(2, 2, 2); // insert code return 1; }
在上面的代码中,如果在// insert code
后插入下面的代码:
s1 - s2 = s1; // ok s1 + s2 = s2; // error!
s1 + s2 = s2;
报error: passing 'const A' as 'this' argument discards qualifiers [-fpermissive];
,原因在于返回const对象能够防止调用后被赋值。
s1 = s1 = s1; // ok (s1 = s1) = s1; // error!
=
是右结合性,因此s1 = s1 = s1
实际上是s1 = (s1 = s1)
没问题,而(s1 = s1) = s1
返回const引用,自然也会报error: passing 'const A' as 'this' argument discards qualifiers [-fpermissive]
A func(const A& s){ // ok return s; } A& funcc(const A& s){ // error! return s; } const A& funccc(A& s){ // ok return s; }
如果把函数func
与funcc
的返回类型改为非const,func
没问题但funcc
报error: binding reference of type 'A&' to 'const A' discards qualifiers
,
func
返回对象(变量),复制构造函数根据s
创建一个与返回类型相同的临时对象,因此返回是否是const无所谓。
funcc
返回引用,因此不会创建临时变量,return s;
返回s
,s
是const引用,如果返回类型是非const,则s
的const状态并不安全,这违反C++的逻辑。
funccc
中return s;
中的s
是非const引用,返回类型是const,此时返回的s
从非const变为const,状态安全,不违反C++逻辑。
总而言之,const
关键字常出现的报错discards qualifiers
,核心原因就在于维护变量状态的安全性。如果编译器认为返回方式不安全,就会报discards qualifiers
。
下篇进入到类的继承章节。