首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么要在返回ostream类时使用引用呢?

在返回ostream类时使用引用的原因是为了避免不必要的对象拷贝和内存开销。ostream类是C++标准库中用于输出的基类,它的派生类比如ostream、ofstream等可以用于输出到不同的目标,比如控制台、文件等。

当我们在函数中返回一个ostream对象时,如果不使用引用,而是直接返回一个ostream对象,那么会触发对象的拷贝构造函数,将原始的ostream对象拷贝一份作为返回值。这个拷贝构造函数可能会涉及到内存的分配和数据的复制,对于大型的ostream对象来说,这样的操作会带来较大的性能开销。

而使用引用作为返回值,可以避免对象的拷贝,直接返回原始的ostream对象的引用。这样做不仅可以提高性能,还可以确保返回的ostream对象与原始对象是同一个对象,可以继续对其进行操作,比如继续输出数据。

总结起来,使用引用作为返回值可以避免不必要的对象拷贝和内存开销,提高性能,并且保证返回的对象与原始对象是同一个对象,可以继续对其进行操作。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Java中如何使用引用数据类型中的

byte、short、int(整数默认)、long、float、double(小数默认)、char、boolean   引用数据类型:、接口、数组、字符串、Lambda等等。   ...注意:字符串、Lambda这两种引用数据类型后面会学习到。 --------------------------------------- Java中如何使用引用数据类型中的?...如果希望使用引用类型中的“”,那么典型用法的一般步骤为: 例如:使用Java中JDK已经写好的扫描器 Scanner。 步骤1:导包。     指定需要使用的目标在什么位置。...导入到的级别。...引用数据类型一般需要创建对象才能使用,格式为: 数据类型 变量名称 = new 数据类型(); 例如:       Scanner sc = new Scanner(System.in);

3.2K10

适合具备 C 语言基础的 C++ 教程(四)

,其中就包括当重载地运算符返回值为引用和非引用两种状态,代码执行效率地高低以及采用在内实现运算符重载函数的方法。...,为了提高效率应该使用的是引用返回。..., 这里为什么返回值是ostream&,是因为对于 cout来说,它是ostream的实例化对象,在使用 cout进行输出的时候,它所遵循的一个输出格式是 cout <<,因此,这里的返回值是 ostream...为什么返回值是引用,是为了满足下面所示代码的运行,同时输出了 m和 p1,结合上述代码,我们来编写主函数,主函数代码如下所示: int main(int argc, char **argv) {...*/ 上述是在外实现运算符重载函数的函数原型,那么如果函数的定义就是在里面实现的,函数又该如何编写

44020

适合具备 C 语言基础的 C++ 入门教程(四)

,其中就包括当重载地运算符返回值为引用和非引用两种状态,代码执行效率地高低以及采用在内实现运算符重载函数的方法。...,为了提高效率应该使用的是引用返回。...ostream&,是因为对于 cout来说,它是ostream的实例化对象,在使用 cout进行输出的时候,它所遵循的一个输出格式是 cout <<,因此,这里的返回值是 ostream。...为什么返回值是引用,是为了满足下面所示代码的运行,同时输出了 m和 p1,结合上述代码,我们来编写主函数,主函数代码如下所示: int main(int argc, char **argv) {...*/ 上述是在外实现运算符重载函数的函数原型,那么如果函数的定义就是在里面实现的,函数又该如何编写

27330

Spark为什么只有在调用action才会触发任务执行(附算子优化和使用示例)?

Spark算子主要划分为两:transformation和action,并且只有action算子触发的时候才会真正执行任务。...微信图片_20200709201425.jpg但初学Spark的人往往都会有这样的疑惑,为什么Spark任务只有在调用action算子的时候,才会真正执行?...那么会产生什么结果? 1....导致map执行完了要立即输出,数据也必然要落地(内存和磁盘) 2. map任务的生成、调度、执行,以及彼此之间的rpc通信等等,当牵扯到大量任务、大数据量,会很影响性能 看到这两点是不是很容易联想到...但是每个Spark RDD中连续调用多个map类算子,Spark任务是对数据在一次循环遍历中完成还是每个map算子都进行一次循环遍历? 答案很确定:不需要对每个map算子都进行循环遍历。

2.3K00

Spark为什么只有在调用action才会触发任务执行(附算子优化和使用示例)?

Spark算子主要划分为两:transformation和action,并且只有action算子触发的时候才会真正执行任务。...但初学Spark的人往往都会有这样的疑惑,为什么Spark任务只有在调用action算子的时候,才会真正执行?咱们来假设一种情况:假如Spark中transformation直接触发Spark任务!...那么会产生什么结果? 1....导致map执行完了要立即输出,数据也必然要落地(内存和磁盘) 2. map任务的生成、调度、执行,以及彼此之间的rpc通信等等,当牵扯到大量任务、大数据量,会很影响性能 看到这两点是不是很容易联想到...但是每个Spark RDD中连续调用多个map类算子,Spark任务是对数据在一次循环遍历中完成还是每个map算子都进行一次循环遍历? 答案很确定:不需要对每个map算子都进行循环遍历。

1.6K30

【C++入门篇】保姆级教程篇【下】

所以我们需要在类型前面使用引用类型,而且我们只是进行比较,加上const更加保险: bool operator==(Const Date &d2) { return _year == d2....我们可以使用在本章稍后面要说的——友元,我们只需要在的内部加上: friend void operator<<(ostream &out, Date const &d); friend...上面是的整体定义,如果想要在细一点,对的成员变量分开定义该如何做?...既然我们不能使用普通成员变量,那我们不妨使用全局变量count来对创建对象进行计数,创建对象在中无非是调用构造函数与拷贝构造,我们只需要在构造和拷贝构造函数内将count+1就行了。...这也就解释了为什么静态成员变量一定要在外初始化。 但是这个时候我们就能直接使用这个成员函数了吗?

11510

【c++】和对象(七)

,避免别人随意修改?...cout,返回值作为左操作数,再进行流插入,所以我们得增加ostream返回值: ostream& operator<<(ostream& out,const Date &d) { out << d...它们通常用于临时的操作,比如传递对象作为函数参数,或者从函数返回对象不需要保留对象的名称 在这个特定的例子中,A(); 创建了一个 A类型的实例,但没有变量名与之关联。...,这样使用就很方便 5.拷贝对象的一些编译器优化 在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝 class A { public: A(int a = 0) :_a(a...如果没有这个特性,临时对象将在表达式结束立即被销毁,这将导致引用悬挂,引用一个已经不存在的对象 void f1(A aa) {} int main() { f1(A(2)); return 0

6820

C++初阶与对象(三):详解复制构造函数和运算符重载

(一般常用const修饰),在用已存在的类型对象创建新对象由编译器自动调用(是构造函数的重载) 拷贝构造函数典型调用场景(自动调用): 使用已存在对象创建新对象 函数参数类型为类型对象 函数返回值类型为类型对象...拷贝构造函数的参数只有一个且必须是类型对象的引用(&),使用传值方式编译器直接报错,因为会引发无穷递归调用 为什么会无限递归:当我们传值调用函数,首先传参–>因为是传值会调用新的一个拷贝构造–>...当然像日期这样的是没必要的。那如果是Stack?...Stack涉及到涉及到资源申请有一个_a指针和动态开辟,使用默认的会发生最初的问题(连续两次释放) 注意:中如果没有涉及资源申请,拷贝构造函数是否写都可以;一旦涉及到资源申请,则拷贝构造函数是一定要写的...所以不能放在内实现,要在全局实现,那又该怎么访问私有成员

14310

【C++】泛型编程 ⑬ ( 模板示例 - 数组模板 | 构造函数和析构函数 的 声明与实现 | 普通成员函数 的 声明与实现 | 外部友元函数 的 声明与实现 )

, 这里使用 Array:: 访问模板 中的 函数 ; 注意 : 如果在 函数参数 和 函数返回值 中 , 使用到了 Array 类型 , 那么也必须加上 实际类型 , 否则编译时会报错...模板内部 的 成员函数即可完成 ; 普通成员函数 的 声明 : 数组下标 运算符 重载 , 返回值是一个 T 类型的 数据 的引用 ; 数组下标 操作符 只有一个 操作数 , 就是 数组的 下标 ,...引用类型的 , 右操作数是 数组本身类型引用 , 返回值是 ostream 引用类型 以便可以进行链式调用 ; 因此 , 该 左移 类型标识 ; 声明时 , 需要在 函数名 和 参数列表之间 注明 泛型类型 ; 实现时 , 不能在 函数名 和 参数列表之间 注明 泛型类型 ; // 左移...// 返回引用就是返回本身 // 将 this 指针解引用, 即可获取数组本身 return *this; } 3、Test.cpp 主函数代码文件 #include "iostream" using

37610

C++初阶 日期的实现(下)

最好使用引用返回,和引用传参,因为这个参数对应的cout是个全局变量不会随着你函数作用域的结束而销毁。...<<endl; return out; } 逻辑没有问题,也确实可以实现,但是我们在具体使用的时候就会出现这样一个问题,没有与之相匹配的运算符,这是为什么?...d1<<cout: 1.2友元并修改 1.2.1简单介绍下友元 如果以后得d1<<cout 那未免有点抽象,我还是更喜欢cout<<d1,这要如何解决,我先揭晓答案,在中实现解决不了这个问题,为什么...这时候就可以介绍到友元,什么是友元,友元就是在中声明一下需要友元的函数,并在前+friend,这就是友元,之后被友元的函数就可以使用里面的私人成员,例如说,我有一个int sum(int a, int...1.2.2修改 有了友元之后我们的修改便只需要在外面把我们的函数写好后,再在Date使用友元扩大我们函数的权限即可 1.3>>重载 有了前面的基础,这个的实现自然是手到擒来的 二、条件判断操作符的实现

9310

EasyC++70,构造函数的一些坑

为什么叫StringBad,主要是为了提示,表示这是一个没有完全开发好的demo。 这里有一个小细节,我们在当中定义的是一个char *也就是字符型指针,而非字符型数组。...这意味着我们在声明当中没有为字符串本身分配空间,而是在构造函数当中使用new来完成的,避免了预先定义字符串的长度。...所以对于静态成员,我们可以在声明之外使用单独的语句进行初始化。因为静态成员变量是单独存储的,并不是对象的一部分。 初始化要在方法文件也就是cpp文件当中,而不是头文件中。...答案是执行callme函数的时候执行的,因为callme函数使用了值传递。当callme函数执行结束,也会调用参数sb的析构函数。...StringBad sailor = sports; StringBad knot; StringBad st = sb; return 0; } 执行一下,得到: 会发现又有负数出现了,这是为什么

15620

【C++】和对象练习——日期的实现

那对于+的重载: 大家有没有注意到我们没有返回引用为什么? 因为我们返回的是啥,是不是tmp,而tmp是一个局部的对象,出了作用域就销毁了,所以我们不能返回引用。...那有时候,有的人为了这个地方能够返回引用,对tmp加了一个static修饰,然后就返回引用。 大家思考一下这样可以吗?...那我们再来重载后置++: 后置++,是先使用,后++,即返回++之前的值。那我们还是可以借助一个临时对象。 但是?...为什么,大家可以调试观察: 会发现这里根本不会进入循环,直接就返回了。...我们把函数声明再放到里面一份,但在前面加一个friend就行了: 那这下我们就可以正常使用<<了: 但是: 这里不支持连续的流插入。为什么

25810

【C++】泛型编程 ⑭ ( 模板示例 - 数组模板 | 容器思想 | 自定义可拷贝 - 深拷贝与浅拷贝 | 自定义可打印 - 左移运算符重载 )

, 向 容器 中插入元素 , 就是拷贝 数据内容 到容器中 , 要将真实的值拷贝进去 , 不是将 引用地址 拷贝进去 , 就是 深拷贝 和 浅拷贝 的问题 ; 下面的示例中 , 自定义中的成员变量...char m_name[32] 是 在定义 , 直接分配好的 , 如果 自定义 中有 指针类型的成员变量 , 如 char* m_name , 涉及到 动态分配内存 , 如果没有定义 拷贝构造函数...& a) { for (int i = 0; i < a.m_length; i++) { // 在一行内输入数据, 使用空格隔开...m_length; i++) { this->m_space[i] = a.m_space[i]; } cout << " 调用 等号 = 操作符重载 函数" << endl; // 返回引用类型...// 返回引用就是返回本身 // 将 this 指针解引用, 即可获取数组本身 return *this; } 3、Test.cpp 主函数代码文件 #define _CRT_SECURE_NO_WARNINGS

17010

C++:与对象(2)

结论:如果类中没有申请资源,析构函数可以不写,直接使用编译器生成的默认析构函数,比如 Date;有资源申请,一定要写,否则会造成资源泄漏,比如Stack(Stack的实例化需要在堆区申请空间...4.3 使用场景 1、使用已存在对象创建新对象 2、函数参数类型为类型对象 3、函数返回值类型为类型对象 为了提高程序效率,一般对象传参,尽量使用引用类型,返回根据实际场景,能用引用...2、为什么要用引用返回? 为了支持连续赋值!! 特性5:赋值运算符只能重载成的成员函数不能重载成全局函数 思考: 1、之前我们实现其他运算符,也是可以定义全局函数啊,大不了传两个参数不就行了。...,cin属于istream 我们还可以发现为什么cout和cin可以自动识别类型??...我们先尝试重载<<打印日期 如果我们在Date内部去对<<重载,要使用的话是这样的 为什么是这样?因为在Date里面定义的话默认Data是第一个操作数,d1<<cout显然不符合我们的习惯。

10610

【C++初阶】和对象(下)

const 变量 可以看到在函数体中对 const 变量是不可以初始化的,所以必须要在初始化列表中初始化; 引用变量 很明显,对于引用变量也不能在函数体中初始化;这里还要注意给引用传参,也要传引用,...答案是:1 随机值 为什么? 这就不得不说到初始化列表的一个有点坑的地方了。...所以,初始化列表最好按照声明的顺序初始化。...三.static 成员 静态成员变量 1.声明为static的成员称为的静态成员,用static修饰的成员变量,称之为静态成员变量; 注意:静态成员变量一定要在外进行初始化,且不加 static...四.友元 友元函数 友元函数可以直接访问的私有成员,它是定义在外部的普通函数,不属于任何,但需要在的内部声明(友元函数并不受访问限定符限制),声明时需要加friend关键字。

9510

C++临时变量的常量性

出错的原因是编译器根据字符串"hello world"构造一个string类型的临时对象,这个临时变量具有const属性,当这个临时变量传递给非const的string&引用类型,无法隐式完成const...形参尽可能地使用const,这样可以使代码更为健壮,将错误暴露于编译阶段。...2.临时变量常量性的原因 为什么临时对象作为引用参数传递,形参必须是常量引用?很多人对此的解释是临时变量是常量,不允许赋值改动,所以作为非常量引用传递,编译器就会报错。...& operator<<(ostream &os, const IntClass &intc); }; //重载operator<< ostream& operator<<(ostream &os,...那编译器为何作出如此限制?如果一个实参以非const引用传入函数,编译器有理由认为该实参会在函数中被修改,并且这个被修改的引用在函数返回后要发挥作用。

1.9K31

C++之面向对象(下)

引用成员变量 原因:引用只有一次初始化的机会,不能再改变 const成员变量 原因:const变量只有一次初始化的机会,不能再改变 自定义类型成员变量(且该类没有默认构造函数) 没有默认构造函数的自定义类型变量...private: int _a2; int _a1; }; int main() { A aa(1); aa.Print(); } 运行结果: 可以看到输出结果是D.1 随机值 为什么会出现这样的情况...d1.Print(); d2.Print(); } 运行结果: 从运行结果我们可以看出,可以像上面的代码中Date d2 = 2023;一样进行创建对象并进行初始化,为什么这样的代码可以实现...但是实际使用中只有cout是第一个形参对象,才能正常使用。...友元函数可以直接访问的私有成员,它是定义在外部的普通函数,不属于任何,但需要在的内部声明,声明时需要加friend关键字。

37140

【C++修行之道】和对象(五)日期的实现、const成员、取地址及const和取地址操作符重载

else { return monthDayArray[month]; } } 问:这个函数为什么不和其他的函数一样放在Date.cpp文件中实现?...前置运算符的语义是“先操作,再返回”。 语义上:前置运算符的语义是先对对象进行递作,然后返回操作后的对象。这里的关键是“操作后的对象”。 效率:返回引用避免了不必要的创建和返回对象的拷贝。...链式操作:通过返回引用,可以支持链式操作。...而temp是临时对象,因此只能以值的方式返回,不能返回引用 1.7 输入输出流重载 // 友元函数声明,声明后可访问私有成员变量 friend ostream& operator<<(ostream&...d.CheckDate()) { cout << "日期非法" << endl; } // 返回输入流的引用,以便支持链式调用 return in; } 为什么参数顺序为(ostream

7910

C++ Primer Plus习题及答案-第十三章

如果返回值为void的,则baseDMA对象仍可以使用单个赋值,但是不能使用连续赋值。...baseDMA,则该方法返回的是一个对象,不是引用,导致返回语句的时候需要复制对象,导致该方法执行速度会有所减慢。...如果基和派生定义了同名的方法,当派生对象调用该方法,被调用的将是哪个方法? 调用派生方法,它取代基定义。仅当派生没有重新定义方法或使用作用域解析运算符,才会调用基方法。 7....仅当派生定义了转换运算符(即包含将基引用作为唯一参数的构造函数)或使用为参数的赋值运算符,相反的赋值才是可能的。 10. 假设定义了一个函数,它将基对象的引用作为参数。...为什么该函数也可以将派生对象作为参数? 应为c++允许基引用指向从该基派生而来的任何类型。 11. 假设定义了一个函数,它将基对象作为参数(即函数按值传递基对象)。

72590
领券