当前位置: 首页> 科技> 名企 > 免费的logo设计制作工具_中国菲律宾混血_杭州疫情最新情况_深圳搜狗seo

免费的logo设计制作工具_中国菲律宾混血_杭州疫情最新情况_深圳搜狗seo

时间:2025/8/5 14:55:19来源:https://blog.csdn.net/2401_86353562/article/details/146533432 浏览次数:2次
免费的logo设计制作工具_中国菲律宾混血_杭州疫情最新情况_深圳搜狗seo

重点内容

视频讲解:《C++Linux编程进阶:从0实现muduo C++网络框架系列》-第5讲.实现C++日志库

代码改动

lesson5代码

  • 实现:base/LogStream.h/cc

  • 实现:base/Logging.h/cc

  • examples/test_basic_log.cc

  • examples/test_logging.cc

特别要注意CMakeLists.txt的 宏定义改动,debug模式时,lesson4声明的DEBUG宏定义和日志库的Debug日志级别符号有冲突,如果不修改会产生意想不到的编译报错。

1. 日志系统整体架构

1.1 日志系统整体架构

LOG_DEBUG << "debug log test";

LOG_INFO << "info log test";

1.2 模块具体作用

1.2.1 日志宏 (LOG_XXX)

比如LOG_DEBUG, LOG_INFO等

提供简洁易用的接口,自动捕获文件名和行号,根据当前日志级别决定是否记录日志,创建临时Logger对象并返回流式接口

使用范例:

LOG_DEBUG << "debug log test";
LOG_INFO << "int: " << 42;

1.2.2 Logger 类

日志系统核心类,管理日志生命周期,提供静态方法控制全局日志行为(级别、输出方式),根据日志级别和上下文创建日志实例,析构时完成日志输出。

LOG_INFO << "info log test"; 实际调用

if (mymuduo::Logger::logLevel() <= mymuduo::Logger::INFO) \mymuduo::Logger(__FILE__, __LINE__).stream() << "info log test";

1.2.3 Logger::Impl 类

日志格式化分为两大模块:

Logger的内部实现类,封装日志格式化逻辑,管理时间戳和源文件信息,处理日志的具体格式,添加行号、文件名等上下文信息。

比如日志格式:20250324 09:08:15.248185 WARN warn 输出 - test_basic_log.cc:26

  • 20250324 09:08:15.248185 时间戳

  • WARN 日志级别打印

  • test_basic_log.cc 文件名

  • :26 行号

1.2.4 LogStream 类

提供流式接口(<<操作符),管理内部缓冲区,实现各种数据类型的格式化转换,特别优化了数值转换效率,支持链式调用。

包括Logger::impl类里的时间戳 日志级别 文件名 行号的缓存,

这里我们重点讲流式接口 <<操作符,范例如下所示:

mymuduo::LogStream logstream;
logstream << "LogStream 输出" << 78 << "abc";
std::cout << "cout: " << logstream.buffer().toString() << std::endl;

输出:

cout: LogStream 输出78abc

1.2.5 FixedBuffer 类

预分配固定大小的内存缓冲区,避免动态内存分配,提供高效的追加、重置等基本操作,作为LogStream的内部存储。

1.2.6 输出函数 (OutputFunc/FlushFunc)

日志最终写入的目的地,函数指针类型(OutputFunc和FlushFunc),允许自定义日志输出目标和刷新方式,可以是控制台、文件、网络套接字或自定义设备,由OutputFunc和FlushFunc控制,支持灵活配置。

1.2.7 日志级别 (LogLevel)

定义日志的严重程度(TRACE、DEBUG、INFO、WARN、ERROR、FATAL),控制日志过滤,配合宏实现条件记录,支持运行时调整。

1.2.8 Fmt 格式化类

结合C风格格式化字符串的灵活性和C++类型安全性,预格式化数据到内部缓冲区,通过<<操作符集成到LogStream中。

  // 测试整数格式化Fmt intFmt("%d", 42);std::cout << "整数格式化: " << intFmt.data() << std::endl;// 测试浮点数格式化Fmt floatFmt("%.2f", 3.14159);std::cout << "浮点数格式化: " << floatFmt.data() << std::endl;

打印输出:

整数格式化: 42 浮点数格式化: 3.14

1.2.9 SourceFile 类

高效处理源文件路径,从完整路径中提取文件名,避免运行时重复计算,优化日志性能,存储在Logger::Impl中提供位置信息。

// 测试不同路径形式
std::cout << "原始的文件名获取:" << __FILE__ << std::endl;
const char* paths[] = {"/home/user/project/file.cpp","src/file.cpp","file.cpp"
};for (const char* path : paths)
{Logger::SourceFile sf(path);std::cout << "原始路径: " << path << "\n";std::cout << "提取文件名: " << sf.data_ << "\n";std::cout << "文件名长度: " << sf.size_ << "\n\n";
}

打印输出

原始的文件名获取:/home/lqf/long/spark_muduo/lesson5/examples/test_basic_log.cc 原始路径: /home/user/project/file.cpp 提取文件名: file.cpp 文件名长度: 8 原始路径: src/file.cpp 提取文件名: file.cpp 文件名长度: 8 原始路径: file.cpp 提取文件名: file.cpp 文件名长度: 8

2 格式化日志输出LogStream类

2.1 核心设计理念

LogStream 的核心设计理念是提供一个高效、类型安全、易用的日志流式接口,主要体现在:

1.流式语法设计:

通过重载 << 操作符,实现类似 std::cout 的链式调用语法

并重载不同的数据类型

  • self& operator<<(short);

  • self& operator<<(unsigned short);

  • self& operator<<(const char* str)

  • self& operator<<(const std::string& v)

每个 << 操作符返回自身引用(self&),支持链式表达式,比如LOG_INFO << "int: " << 42;

2.高效内存管理(设计FixedBuffer类):

  • 使用预分配的固定大小缓冲区而非动态内存分配

  • 避免了频繁的内存分配/释放操作,减少内存碎片

2.2 设计框架图

2.3 核心实现分析

2.3.1 内存管理策略

LogStream 通过 FixedBuffer 模板类管理内存,采用两种预定义大小:

// 在detail命名空间中定义两种常用缓冲区大小
const int kSmallBuffer = 4000;         // 4KB,用于一般日志消息
const int kLargeBuffer = 4000*1000;    // 4MB,用于特别长的日志消息// 定义LogStream使用的缓冲区类型
typedef detail::FixedBuffer<detail::kSmallBuffer> Buffer;

FixedBuffer 的核心在于预分配内存并使用指针跟踪当前位置:

template<int SIZE>
class FixedBuffer : noncopyable {
private:char data_[SIZE];  // 固定大小的字符数组char* cur_;        // 当前写入位置public:FixedBuffer() : cur_(data_) {}void append(const char* buf, size_t len) {if (avail() > static_cast<int>(len)) {memcpy(cur_, buf, len);cur_ += len;}}// 其他辅助方法...
};

这种设计避免了动态内存分配,特别适合短生命周期、高频调用的日志场景。

2.3.2 优化的数值转换算法

LogStream 对数值转换做了专门优化,使用自定义的转换算法替代标准库函数:

// Wilson的高效整数转字符串算法
template<typename T>
size_t convert(char buf[], T value) {T i = value;char* p = buf;do {int lsd = static_cast<int>(i % 10);i /= 10;*p++ = zero[lsd];  // 使用预定义的字符表  查表获取数字} while (i != 0);if (value < 0) {*p++ = '-';}*p = '\0';std::reverse(buf, p);  // 反转得到正确顺序return p - buf;
}// 十六进制转换算法,用于指针
size_t convertHex(char buf[], uintptr_t value) {// 类似实现...
}

这些算法直接操作字符数组,避免了格式化函数的开销和临时对象创建。

2.3.3 流式接口实现

LogStream 通过大量的操作符重载实现流式接口:

// 将不同类型的数据格式化写入缓冲区
LogStream& LogStream::operator<<(int v) {formatInteger(v);return *this;  // 返回自身引用,支持链式调用
}LogStream& LogStream::operator<<(const char* str) {if (str) {buffer_.append(str, strlen(str));}else {buffer_.append("(null)", 6);}return *this;
}// 其他类型的重载...

关键是每个操作符都返回自身引用(*this),使得多个 << 操作可以连续调用。

2.4 类型安全与格式化

LogStream 通过模板和静态断言提供类型安全保证:

// 将所有整数类型统一处理
template<typename T>
void LogStream::formatInteger(T v) {// 实现整数格式化...
}// Fmt类使用静态断言确保类型安全
template<typename T>
Fmt::Fmt(const char* fmt, T val) {// 编译期类型检查static_assert(std::is_arithmetic<T>::value == true, "Must be arithmetic type");// 格式化...
}

3 章节总结

1.重点内容:

  1. 理解如何使用日志级别控制日志是否记录

  2. 理解LogStream如何使用输出操作符 以C++ cout方式格式化日志。

2.扩展:

  1. 异步日志支持:

  2. 将 LogStream 与异步日志系统集成,提高性能

  3. 设计双缓冲机制,支持高并发场景

  4. 日志压缩与滚动:

  5. 支持日志文件自动滚动和压缩

  6. 实现日志清理策略,避免磁盘占用过多

关键字:免费的logo设计制作工具_中国菲律宾混血_杭州疫情最新情况_深圳搜狗seo

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: