【Effective C++】读书笔记 Part5 实现

条款28:避免返回handles指向对象内部成分

避免返回handles(包括references,指针,迭代器)指向对象内部。遵守这个条款可以增加封装性,帮助const成员函数的行为更像要一个const,并将发生diangling handles的可能性降至最低。

对于一个const成员函数,如果其返回reference指向对象本身,那么客户就可以通过调用这个成员函数获得的reference修改对象。这也违背了const成员函数的初衷,虽然其并没有修改相应的对象。

示例如下:

class Point
{
public:Point(int x,int y);void SetX(int val);void SetY(int val);
};//一个矩形需要有的元素,左上角和右下角
struct RectData
{ Point ulhc; Point lrhc;
}; //矩形的定义
class Rectangle
{
public: ... Point& upperLeft() const { return pData->ulhc; }Point& lowerRight() const { return pData->lrhc; }private: std::shared_ptr<RectData> pData; ...
}; 

对于upperLeft()和lowerRight()其均为const成员函数,但是其返回了reference指向自身对象,所以可以通过如下方式来修改对象的值

Point coord1(0,0);
Point coord2(100,100);
const Rectangle rec(coord1, coord2);
rec.upperLeft().setX(50);//现在rec变成从(50,0)到(100,100)

这里有两个需要注意点:

  1. 成员变量的封装性最多只等与“返回其reference”的函数的访问级别。
  2. 如果const成员函数传出一个reference指向自身对象,那么函数的调用者可以通过这个引用来修改对象。

如果将上述函数改为返回 const的reference。
如下:

//矩形的定义
class Rectangle
{
public: ... const Point& upperLeft() const { return pData->ulhc; }const Point& lowerRight() const { return pData->lrhc; }private: std::shared_ptr<RectData> pData; ...
}; 

确实可以解决通过函数调用而导致对象改变的状态。

但是却又可能导致新的问题,因为返回的reference可能会指向一个已经不存在的对象!

考虑如下代码:


//某函数以by-value形式返回Rectangleconst Rectangle CreateRectangle();const Point * p = &(CreateRectangle().upperLeft());

注意CreateRectangle返回的是一个Rectangle类型的临时变量,在语句结束之后,将会被自动销毁,所以对应的p指针显然是指向一个以及不存在的Rectangle对象中的Point。

综上,就有了返回一个handle代表对象内部成分总是危险的。

【Effection C++】读书笔记 条款28:避免返回handles指向对象内部成分相关推荐

  1. vb 根据pid获取句柄_C++中避免返回指向对象内部的句柄(handles)

    点蓝色字关注"CurryCoder的程序人生" 微信公众号:CurryCoder的程序人生 欢迎关注我,一起学习,一起进步! 1.问题的引入 假如你正在给一个应用写一个矩形类,这个 ...

  2. 【Effection C++】读书笔记 条款01~条款04

    [Effection C++]读书笔记 Part1 让自己习惯C++ 条款01:视C++为一个语言联邦 将C++视为一个由相关语言组成的联邦.在其某个次语言中,各种守则简单易懂,容易记住.但当从一个次 ...

  3. 【Effection C++】读书笔记 条款10~条款12

    [Effection C++]读书笔记 Part2 构造/析构/赋值运算 条款09:绝不在构造和析构函数中调用virtual函数 构造函数和析构函数期间不要调用virtual函数,虽然语法上并不会有错 ...

  4. 【Effection C++】读书笔记 条款41~条款42

    [Effection C++]读书笔记 Part7 模板与泛型编程 条款41:了解隐式接口和编译器多态 本条款主要是讲述了两个概念,隐式接口和编译器多态 1. 显示接口和隐式接口 显示接口是由函数的签 ...

  5. 【Effection C++】读书笔记 条款05~条款06

    [Effection C++]读书笔记 Part2 构造/析构/赋值运算 条款05:了解C++默认编写并调用哪些函数 编译器可以暗自为class创建default构造函数,copy构造函数,copy ...

  6. 【Effection C++】读书笔记 条款07~条款08

    [Effection C++]读书笔记 Part2 构造/析构/赋值运算 条款07:为多态基类声明virtual析构函数 带有多态(polymorphic)性质的base classes应该声明一个v ...

  7. 【Effection C++】读书笔记 条款20~条款23

    [Effective C++]Part4 设计与声明 条款20:宁以pass-by-reference-to-const替换pass-by-value 尽量以pass-by-reference-to- ...

  8. 【Effection C++】读书笔记 条款29~条款30

    [Effective C++]读书笔记 Part5 实现 条款29:为异常安全而努力是值得的 当异常被抛出时,待哟异常安全性的函数会: 不泄漏任何资源. 不允许数据败坏. 异常安全函数提供以下三个保证 ...

  9. 【Effection C++】读书笔记 条款27:尽量少做转型动作

    [Effective C++]读书笔记 Part5 实现 条款27:尽量少做转型动作 C++中的类型转换语法 类型转换语法主要有三种不同的形式: (T)expression //将expression ...

最新文章

  1. Go 学习笔记(22)— 并发(01)[进程、线程、协程、并发和并行、goroutine 启动、goroutine 特点,runtime 包函数]
  2. 腾讯云发布全链路数据开发平台WeData,企业数据开发门槛降低60%
  3. Nginx配置https,反向代理多实例tomcat的操作记录
  4. android url webview,android - webview获取到当前页面的url
  5. 如何快速开发一个 Dubbo 应用?(含沙龙报名)
  6. es6 Proxy 简介
  7. linux noprobe参数,find 命令的参数详解
  8. nohup与区别于使用
  9. ValueError: Cannot feed value of shape (784,) for Tensor 'Placeholder:0', which has shape '(?, 784)'
  10. [安全攻防进阶篇] 八.那些年的熊猫烧香及PE病毒行为机理分析
  11. [深度学习从入门到女装]PReLU
  12. ESP8266自动下载电路分析
  13. 软件工程:数据流图和结构图怎么画?
  14. 物联网让生活更加轻松的五种方式
  15. MySQL-索引及其原理
  16. WindowManager LayoutParams 上
  17. 高人总结,告诉你输入输出阻抗是怎么回事?
  18. 加一度详解百度线索通,竞价新手必看福利!
  19. 分享一下身边朋友自学android开发及找工作的那些事!【不足勿喷】
  20. 有道打赏视频/支付已对接/自带资源

热门文章

  1. html制作网页案例代码-HTML5+CSS大作业——三八女人节主题设计(1页)-
  2. linux truncate 命令,如何在Linux中截断truncate文件
  3. 明日之后今天又又又更新了:熟练度溢出问题已解决,即将开放18庄?
  4. Web分辨率以及网页测试
  5. 用计算机学数学日记,【精华】小学生数学日记十篇
  6. PHP根据身份证号计算年龄和年龄分段
  7. 逝去的流年,渐行渐远,慢慢成为眼角的回忆
  8. CCS5.5 仿真配置文件操作说明
  9. Unity灯光效果及设置详解
  10. 电动自行车电池[充不进电][铅酸电池][饿死]重新激活