Effective C++ 第一章:让自己习惯C++

本文摘自《EffectiveC++》(第三版),深入探讨C++的联邦语言特性,强调使用const、enum、inline替代#define,详述const的多场景应用,并提出对象初始化的最佳实践。

序言

Effective C++ 的系列博文是本人学习了《Effective C++》(第三版)之后的学习整理,大部分内容来源于原书。为了更方便地回顾和复习,所以将一些重要的知识点提取出来。分享给大家一起进步学习 ?

第一章:让自己习惯C++

条款1:视C++为一个语言联邦

将C++视为一个由相关语言组成的联邦而非单一的语言。可以理解为四个:

  • C:区块(block)、语句(statements)、预处理器(preprocessor)、内置数据类型、数组(array)、指针(pointers)等
  • Objective-C:类(class)、封装、继承、多态、虚函数等
  • Template C++:泛型编程
  • STL:template程序库。包含容器、迭代器、算法以及函数对象等。

条款2:尽量以const,enum,inline替换#define

让编译器替换预处理器会更好。因为#define 不被视为语言的一部分。因为所使用的名称可能并没有进入记号表(symbol table)

#define ASPECT_RATIO 1.653
//替换为
const double AspectRatio = 1.653;

define无法实现创建class专属常量,只能使用const

class Game
{
private:
    static const int NumTurns = 5;
};

有些旧式编译器不支持static成员在其声明式上获得初值。可以使用enum代替:

class GamePlayer
{
private:
   enum { NumTurns = 5; }
   int scores[NumTurns];
};

宏函数

#define CALL_WITH_MAX(a,b) f((a)>(b) ? (a): (b))

会遭遇传参等一些不可预料的行为,建议使用inline函数代替。

  • 我们并不是不再使用预处理器,而是降低需求。我们仍然需要使用#include #ifdef/#ifndef

条款3:尽可能使用const

  • const 指针问题
char greeting[] = "Hello";
const char* p = greeting;  //non-const pointer, const data
char* const p = greeting;  //const pointer, non-const data
const char* const p = greeting;  //const pointer, const data
  • 常量迭代器:迭代器所指的东西不可被改动
std::vector<int> vec;
const std::vecotr<int>::iterator iter = vec.begin();
  • const成员函数:可以知道哪个函数可以改动对象内容而哪个函数不行.
    在const函数中不可以修改对象内任何non-static成员
class Text
{
public:
     const char& operator[](int position) const
     { return text[position];}
}
  • 可修改常量mutable
class CText
{
public:
     mutable size_t textLength;  //这些成员变量即使在mutable中也可以被修改
	 size_t length() const
	 {
	 	textLength = 1;
	 }
}
  • 常量的变换
//const_cast 常量移除
const_cast<char&>(var);
//static_cast 转为const
static_cast<char&>(var);

条款4:确定对象被使用前已先被初始化

数组(来自C++的C部分)不保证其内容被初始化,而vector(来自C++的STL)部分却有这个保证。

  • 构造函数
class ABEntry
{
public:
      ABEntry(const string& name, const string address);
private:
      string thename;
	  string theaddress;
};
ABEntry::ABEntry(const string& name, const string address)
{
      thename = name;
	  theaddress = address;
}

解析:会先调用默认构造函数为thename, theaddress设初值,然后立刻再对它们赋予新值。【先调用默认(default)构造函数,然后是复制操作(copy assignment)】


效率更高的写法:成员初值列

ABEntry::ABEntry(const string& name, const string address):thename(name),theaddress(address)
{ }

解析:这个版本的构造函数和上一个的最终结果相同,但通常效率较高,因为初值列中针对各个成员变量而设的实参,被拿去作为各成员变量之构造函数的实参。【只调用一次复制(copy)构造函数】


对于内置变量来说(如int)其实初始化和赋值的成本相同,但为了一致性,最好使用成员初始值来初始化。

  • 不同编译单元内定义之non-local static 对象 的初始化顺序
  1. static对象:
    函数内的static对象称为local static对象,其他static对象称为non-local static对象。

  2. 编译单元:
    单一目标文件(single object file)的那些源码。基本上是单一源码加上所含入的头文件。

  3. 如果某编译单元的某个non-local static对象的初始化动作使用了另一个编译单元内的某个non-local static对象,它所用到的这个对象可能尚未被初始化。因为C++对于定义在不同编译单元内的non-local static对象的初始化次序并无明确定义。

class FileSystem{
public:
      std::size_t numDisks() const;
};
extern FileSystem tfs;
//
class Directory{
public:
      Directory(parms);
};
Directory::Directory(parms)
{
    std::size_t disk = tfs.numDisks();  //无法确定tfs在tempDir之前先被初始化
}
Directory tempDir(parms);

解决办法:将每个non-local static对象搬到自己的专属函数内。这些函数返回一个reference指向它所含的对象。

class FileSystem{...};
FileSystem& tfs()
{
     static FileSystem fs;
	 return fs;
}
class Directory{...};
Directory::Directory(parms)
{
     std::size_t disks = tfs().numDisks();
}
Directory& tempDir()
{
     static Directory td;
	 return td;
}
**项目名称:** 基于Vue.js与Spring Cloud架构的博客系统设计与开发——微服务分布式应用实践 **项目概述:** 本项目为计算机科学与技术专业本科毕业设计成果,旨在设计并实现一个采用前后端分离架构的现代化博客平台。系统前端基于Vue.js框架构建,提供响应式用户界面;后端采用Spring Cloud微服务架构,通过服务拆分、注册发现、配置中心及网关路由等技术,构建高可用、易扩展的分布式应用体系。项目重点探讨微服务模式下的系统设计、服务治理、数据一致性及部署运维等关键问题,体现了分布式系统在Web应用中的实践价值。 **技术架构:** 1. **前端技术栈:** Vue.js 2.x、Vue Router、Vuex、Element UI、Axios 2. **后端技术栈:** Spring Boot 2.x、Spring Cloud (Eureka/Nacos、Feign/OpenFeign、Ribbon、Hystrix、Zuul/Gateway、Config) 3. **数据存储:** MySQL 8.0(主数据存储)、Redis(缓存与会话管理) 4. **服务通信:** RESTful API、消息队列(可选RabbitMQ/Kafka) 5. **部署与运维:** Docker容器化、Jenkins持续集成、Nginx负载均衡 **核心功能模块:** - 用户管理:注册登录、权限控制、个人中心 - 文章管理:富文本编辑、分类标签、发布审核、评论互动 - 内容展示:首页推荐、分类检索、全文搜索、热门排行 - 系统管理:后台仪表盘、用户与内容监控、日志审计 - 微服务治理:服务健康检测、动态配置更新、熔断降级策略 **设计特点:** 1. **架构解耦:** 前后端完全分离,通过API网关统一接入,支持独立开发与部署。 2. **服务拆分:** 按业务域划分为用户服务、文章服务、评论服务、文件服务等独立微服务。 3. **高可用设计:** 采用服务注册发现机制,配合负载均衡与熔断器,提升系统容错能力。 4. **可扩展性:** 模块化设计支持横向扩展,配置中心实现运行时动态调整。 **项目成果:** 完成了一个具备完整博客功能、具备微服务典型特征的分布式系统原型,通过容器化部署验证了多服务协同运行的可行性,为云原生应用开发提供了实践参考。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值