《C++面向对象高效编程(第2版)》——3.15 函数返回值

简介:

本节书摘来自异步社区出版社《C++面向对象高效编程(第2版)》一书中的第3章,第3.15节,作者: 【美】Kayshav Dattatri,更多章节内容可以访问云栖社区“异步社区”公众号查看。

3.15 函数返回值

C++面向对象高效编程(第2版)
许多函数向主调函数返回值、引用或指针。要正确和高效地使用它们,必须先理解它们的含义。可能有以下几种模式返回:

T X::f();     // 按值返回T
T* X::f();    // 返回T类对象的指针/地址
const T* X::f(); // 返回指向const T类对象的指针
T& X::f();    // 返回对T对象的引用
const T& X::f(); // 返回对const T类对象的引用```
(1)绝不返回对局部变量的引用(或指向局部变量的指针)。一旦离开函数,局部变量将被销毁,但在此之后,引用(或指针)仍然存在,它依旧引用(或指向)某些已不存在的对象。

(2)如果在函数内部创建新对象,并且希望将该对象的所有权移交给主调函数,那么该函数必须返回一个指针。主调函数拥有返回的指针所指向的内存。当被调函数创建了一个新对象(或指向某对象的指针),但却不能控制该对象的生存期时,通常会出现这种情况。为这样的函数使用一种命名约定是个不错的想法(如CreateXXX())。而且,如果存在这样的函数,也必须在文档中清楚地说明。这与之前讨论的采用语义相反。例如,在TPerson类中,有一个成员函数:

class TPerson {
  public:
    // ...
    char* CreateNameOfPerson()const; // Person类的成员
};`
假设,CreateNameOfPerson()用于为名称中的字符分配内存,且返回指向该字符的指针(由主调函数所拥有)。当不再需要它时,主调函数应释放内存。只有在指针返回值时,才能转移动态对象的所有权。若返回引用或值则无法转移所有权(至少很不容易)。如果不想返回指针,可以将指针包含在对象中(像C++库中的string类对象),然后按值返回对象。另外,我们也可以使用某些回收程序对象(C++中的auto_prt),自动地删除从这种函数返回的指针,将在下一章中将介绍。

(3)如果不允许主调函数修改返回的指针所指向的字符(或者对象),则返回指向const的指针。在TPerson类中:

class TPerson {
  public:
  // ... 
  const char* GetNameOfPerson() const;
};```
这并不意味着转移了内存的所有权。主调函数只能读取返回的指针所指向的内容,不能删除它(若删除它,在编译时将检测出错误)。如果从`const`函数返回指针(无论何种原因),应该返回指向数据成员的`const`指针。若返回指向数据成员的非`const`指针,将抵销`const`函数的优点,编译器会检测出这样的错误。当按值返回的开销很大时(或者语义上不正确时),推荐使用返回指向`const`的指针(指向一个数据成员),但是,主调函数不应该修改指针所指向的内容。客户必须尊重指针的`const`性质,并且在使用它时不转换它的类型。

警告:
记住:绝不返回指向某个数据成员的非`const`指针。否则,不仅会为你带来不必要的麻烦,而且,还会把实现数据暴露给客户,从而削弱了抽象,破坏了数据封装。
如果从函数返回值可能失败,那么,从函数返回指针是唯一的选择。通过返回空指针可以轻松完成。空指针能指出函数本应返回的值出现问题或不存在(如上面示例中的GetNameOfPerson)。这就是为什么从函数返回指针很常见的原因之一(除了上面提到的其他原因之外)。

(4)如果要返回一个基本类型(`char`、`int`、`long`等),那么,按值返回和按引用或指针返回效率相同。但是,按值返回较为安全和容易,而且易于理解。

(5)在某些情况下(如`operator+`),无法返回引用,因为函数的结果未知(而且无法提前计算),正确的实现将要求按值返回(在函数内部创建一个临时变量)。这是实现这种函数最佳和最安全的方法,将在第8章中介绍。
相关文章
|
29天前
|
API 数据库 C语言
【C/C++ 数据库 sqlite3】SQLite C语言API返回值深入解析
【C/C++ 数据库 sqlite3】SQLite C语言API返回值深入解析
169 0
|
7天前
|
C++
面向对象的C++题目以及解法2
面向对象的C++题目以及解法2
13 1
|
13天前
|
编译器 C语言 C++
【C++初阶(九)】C++模版(初阶)----函数模版与类模版
【C++初阶(九)】C++模版(初阶)----函数模版与类模版
18 0
|
17天前
|
存储 人工智能 机器人
【C++面向对象】C++图书管理系统 (源码)【独一无二】
【C++面向对象】C++图书管理系统 (源码)【独一无二】
|
22天前
|
存储 人工智能 BI
【C++面向对象】C++银行卡管理系统(源码+论文)【独一无二】
【C++面向对象】C++银行卡管理系统(源码+论文)【独一无二】
|
23天前
|
存储 缓存 C++
C++链表常用的函数编写(增查删改)内附完整程序
C++链表常用的函数编写(增查删改)内附完整程序
|
25天前
|
存储 安全 编译器
【C++】类的六大默认成员函数及其特性(万字详解)
【C++】类的六大默认成员函数及其特性(万字详解)
35 3
|
28天前
|
安全 程序员 C++
【C++ 基本知识】现代C++内存管理:探究std::make_系列函数的力量
【C++ 基本知识】现代C++内存管理:探究std::make_系列函数的力量
101 0
|
29天前
|
设计模式 安全 C++
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
71 2
|
30天前
|
安全 编译器 程序员
【C++ 泛型编程 高级篇】C++ 编程深掘:静态成员函数检查的艺术与实践
【C++ 泛型编程 高级篇】C++ 编程深掘:静态成员函数检查的艺术与实践
63 0

热门文章

最新文章