本文主要是介绍【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的思考总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!