【C++】关于左移运算符<<重载、cout、endl的思考总结

2024-03-14 08:40

本文主要是介绍【C++】关于左移运算符<<重载、cout、endl的思考总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

左移运算符重载如下:

#include<iostream>
#include"main.h"
using namespace std;
void operator<<(ostream &out,Maker &m){out<<m.id<<" "<<m.age<<endl;
}
int main(){Maker m(12,10);cout<<m;system("pause");return 0;
}

为啥重载函数的ostream的参数必须是引用?

因为不引用的话,相当于传值,也就是要拷贝一份cout对象,但是ostream里面的拷贝构造函数是protected的,无法拷贝。

如何实现连续地输出cout<<m<<endl;?

需要在运算符重载的时候返回cout的引用。

#include<iostream>
#include"main.h"
using namespace std;
ostream& operator<<(ostream &out,Maker &m){out<<m.id<<" "<<m.age<<endl;
}
int main(){Maker m(12,10);cout<<m;system("pause");return 0;
}

endl本质是啥?和’\n’有什么不同?

在c++的源码中,endl就是一个内联函数,完成换行\n和刷新缓冲区的功能,源码截图如下:
在这里插入图片描述

为什么endl作为一个内联函数可以被用在<<的右边?

源码如下:
在这里插入图片描述
依然是在ostream中写的成员函数实现<<运算符重载,这里面的*_Pfn是函数指针,当我们传递endl给<<的时候,endl作为函数名也表示函数地址,所以根据这里的重载运算符,可以实现cout<<endl;调用endl这个内联函数。

总结

实际上cout作为ostream的对象完成c++中的输出功能,都是在ostream中进行运算符重载实现的。
在这里插入图片描述

关于ostream是否为单例模式

根据ostream对构造函数的定义,只有一个带参数的构造函数是public的:

public:
explicitbasic_ostream(__streambuf_type* __sb){ this->init(__sb); }

通过这个构造函数可以再构造一个ostream对象:

#include <iostream>
#include <fstream>using namespace std;int main()
{filebuf buf;//streambuf类型的构造函数是保护类型,filebuf是其子类。if ( buf.open("/proc/self/fd/1", ios::out) == nullptr ){cerr << "stdout open failed" << endl;return -1;}ostream out(&buf);return 0;
}

可知ostream并不是单例模式。

至于ostream的拷贝构造函数和赋值运算符重载函数都无法被调用。

C++11版本中对这两个函数直接delete:

protected:basic_ostream(){ this->init(0); }#if __cplusplus >= 201103L// Non-standard constructor that does not call init()basic_ostream(basic_iostream<_CharT, _Traits>&) { }basic_ostream(const basic_ostream&) = delete;basic_ostream(basic_ostream&& __rhs): __ios_type(){ __ios_type::move(__rhs); }// 27.7.3.3 Assign/swapbasic_ostream& operator=(const basic_ostream&) = delete;basic_ostream&operator=(basic_ostream&& __rhs){swap(__rhs);return *this;}

C++98可以用private继承boost::noncopyable达到同样的目的,在《Effective C++ 3rd》的条款06中有几句话:

可以将copy构造函数或copy assignment操作符【注:赋值运算符】声明为private以阻止编译器暗自创建其专属【注:默认】版本,同时阻止人们调用它。


一般而言这个做法并不绝对安全,因为成员函数和友元函数还是可以调用(这两个)private函数。如果不去定义它们,那么如果某些人不慎调用任何一个,会获得一个连接错误(linkage error)。


“将成员函数生命为private而且故意不实现它们”这一伎俩是如此为大家接受,因而被用在C++ iostream程序库中阻止copying行为【注:copying行为即调用拷贝构造函数和调用赋值运算符重载函数】


将连接器错误移至编译器是可能的,只要将copy构造函数和copy assignment操作符声明为private就可以办到,但不是在自身这个类中,而在一个专门为了阻止copying动作而设计的base class 内。

即使用noncopyable基类可以安全有效避免copying行为。

这篇关于【C++】关于左移运算符<<重载、cout、endl的思考总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/807856

相关文章

C++类和对象之初始化列表的使用方式

《C++类和对象之初始化列表的使用方式》:本文主要介绍C++类和对象之初始化列表的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C++初始化列表详解:性能优化与正确实践什么是初始化列表?初始化列表的三大核心作用1. 性能优化:避免不必要的赋值操作2. 强

C++迭代器失效的避坑指南

《C++迭代器失效的避坑指南》在C++中,迭代器(iterator)是一种类似指针的对象,用于遍历STL容器(如vector、list、map等),迭代器失效是指在对容器进行某些操作后... 目录1. 什么是迭代器失效?2. 哪些操作会导致迭代器失效?2.1 vector 的插入操作(push_back,

Linux区分SSD和机械硬盘的方法总结

《Linux区分SSD和机械硬盘的方法总结》在Linux系统管理中,了解存储设备的类型和特性是至关重要的,不同的存储介质(如固态硬盘SSD和机械硬盘HDD)在性能、可靠性和适用场景上有着显著差异,本文... 目录一、lsblk 命令简介基本用法二、识别磁盘类型的关键参数:ROTA查询 ROTA 参数ROTA

Kotlin运算符重载函数及作用场景

《Kotlin运算符重载函数及作用场景》在Kotlin里,运算符重载函数允许为自定义类型重新定义现有的运算符(如+-…)行为,从而让自定义类型能像内置类型那样使用运算符,本文给大家介绍Kotlin运算... 目录基本语法作用场景类对象数据类型接口注意事项在 Kotlin 里,运算符重载函数允许为自定义类型重

C#如何调用C++库

《C#如何调用C++库》:本文主要介绍C#如何调用C++库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录方法一:使用P/Invoke1. 导出C++函数2. 定义P/Invoke签名3. 调用C++函数方法二:使用C++/CLI作为桥接1. 创建C++/CL

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解