c/c++ 拷贝控制 右值与const引用
拷贝控制 右值与const引用
背景:当一个函数的返回值是自定义类型时,调用侧用什么类型接收??
1,如果自定义类型的拷贝构造函数的参数用const修饰了:可以用下面的方式接收。
Test t2 = fun(t1);
2,如果自定义类型的拷贝构造函数的参数没有用const修饰了:必须用下面的方式接收
const Test& t2 = fun(t1);
Test t2 = fun(t1);//编译不通过
编译错误:
cannot bind non-const lvalue reference of type ‘Test&’ to an rvalue of type ‘Test’
解释:
第一种条件下,用const了,由于在编译阶段,要调用Test的拷贝构造函数(其实,在运行的时候是没有调用这个拷贝构造函数的,编译器进行了优化,避免了一次没有意义的拷贝。),参数是fun(t1)的返回值,类似Test(func(t1)),但是这个参数,也就是函数的返回值是右值(临时对象),由于右值必须是const属性的,所以加上了const,就满足了右值的需要,所以可以编译通过,这时t2是可以被改变的;如果没有加const,用第一种方式(Test t2 = fun(t1);)接收,就会编译错误。
第二种条件下,没有使用const,由于在编译阶段,要调用Test的拷贝构造函数,因为fun(t1)的返回值是右值,右值有const属性,所以编译器没有找到匹配的拷贝构造函数,就自己合成了一个拷贝构造函数。由编译器合成的这个拷贝构造函数就只能用上面写的方式接收,至于为什么,还没搞不懂!!!
代码:
#include <iostream>
using namespace std;
class Test{
public:
Test(int d = 0):data(d){
cout << "C:" << d << " " << this << endl;
}
//如果参数没有const修饰,下面②处代码编译不过;
Test( Test &t){
cout << "Copy:" << t.data << " " << this << endl;
data = t.data;
}
~Test(){
cout << "F:" << this->data << "->" << this << endl;
}
int getData()const{
return data;
}
void setData(int d){
data = d;
}
private:
int data;
};
Test fun(Test &x){
int value = x.getData();
Test tmp(value);
return tmp;
}
int main(){
Test t1(100);
//编译器优化了,当把fun(t1)的返回值拷贝给t2时,应该调用拷贝构造函数,但是编译器优化了,就没有调用这次多余的拷贝构造函数,直接把让t2所占用的内存就是右值(fun(t1))所开辟的内存.
const Test& t2 = fun(t1);----->①
//Test t3 = fun(t1); ----->②
//t2.setData(11);
//std::cout << t2.getData() << std::endl;
//Test t2(fun(t1));
return 0;
}
c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854
c/c++ 拷贝控制 右值与const引用的更多相关文章
- c++中的左值与右值
左值(lvalue)和右值(rvalue)是 c/c++ 中一个比较晦涩基础的概念,不少写了很久c/c++的人甚至没有听过这个名字,但这个概念到了 c++11 后却变得十分重要,它们是理解 move/ ...
- c++11 右值引用和移动语义
什么是左值.右值 最常见的误解: 等号左边的就是左值,等号右边的就是右值 左值和右值都是针对表达式而言的, 左值是指表达式结束后依然存在的持久对象 右值是指表达式结束时就不再存在的临时对象区分: 能对 ...
- c/c++ 右值引用
c/c++ 右值引用 转自:https://www.cnblogs.com/catch/p/3500678.html 左值(lvalue)和右值(rvalue)是 c/c++ 中一个比较晦涩基础的概念 ...
- C++中让人忽视的左值和右值
前言 为了了解C++11的新特性右值引用,不得不重新认识一下左右值.学习之初,最快的理解,莫过于望文生义了,右值那就是赋值号右边的值,左值就是赋值号左边的值.在中学的数学的学习中,我们理解的是,左值等 ...
- C++的那些事:类的拷贝控制
1,什么是类的拷贝控制 当我们定义一个类的时候,为了让我们定义的类类型像内置类型(char,int,double等)一样好用,我们通常需要考下面几件事: Q1:用这个类的对象去初始化另一个同类型的对象 ...
- [C++ Primer] : 第13章: 拷贝控制
拷贝, 赋值与销毁 当定义一个类时, 我们显示地或隐式地指定在此类型的对象拷贝, 移动, 赋值和销毁时做什么. 一个类通过定义5种特殊的成员函数来控制这些操作, 包括: 拷贝构造函数, 拷贝赋值运算符 ...
- 【C++】C++的拷贝控制
目录结构: contents structure [-] 拷贝.赋值与销毁 拷贝构造函数 拷贝初始化 参数和返回值 拷贝赋值运算符 析构函数 三五法则 拷贝控制和资源管理 交换操作 对象移动 右值引用 ...
- 《C++ Primer》笔记 第13章 拷贝控制
拷贝和移动构造函数定义了当用同类型的另一个对象初始化本对象时做什么.拷贝和移动赋值运算符定义了将一个对象赋予同类型的另一个对象时做什么.析构函数定义了当此类型对象销毁时做什么.我们称这些操作为拷贝控制 ...
- C++智能指针之shared_ptr与右值引用(详细)
1. 介绍 在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露.解决这个问题最有效的方法是使用智能指针(smart pointer).智能指针是存储指向动态分配(堆)对象指针 ...
随机推荐
- mac连接windows远程桌面及文件复制
最近更换mac办公,但由于之前是用windows,所以很多文件项目之类的东西都还在windows电脑中,一次都传到mac上又会比较占内存,并且使用率也不高,感觉不划算.但每次想用的时候,在从windo ...
- python高级-迭代器(18)
一.什么是迭代器 迭代是访问集合元素的⼀种⽅式. 迭代器是⼀个可以记住遍历的位置的对象. 迭代器对象从集合的第⼀个元素开始访问,直到所有的元素被访问完结束. 迭代器只能往前不会后退 二.可迭代对象 直 ...
- bootstrap分页插件的使用
项目中需要实现文章列表的分页显示,由于使用了bootstrap框架,所以我们选择bootstrap的分页实现方法.网上有一些这方面的介绍文章,并且也有相关的示例程序.这里结合我们的项目,介绍一下使用b ...
- [Abp 源码分析]四、模块配置
0.简要介绍 在 Abp 框架当中通过各种 Configuration 来实现模块的配置,Abp 本身提供的很多基础设施功能的一些在运行时的行为是通过很多不同的 Configuration 来开放给用 ...
- C# int数据类型呵呵
int16=short; int32=int; int64=long; Int16 值类型表示值介于 -32768 到 +32767 之间的有符号整数. Int32 值类型表示值介于 -2,147,4 ...
- mybatis中的动态SQL
在实际开发中,数据库的查询很难一蹴而就,我们往往要根据各种不同的场景拼接出不同的SQL语句,这无疑是一项复杂的工作,我们在使用mybatis时,mybatis给我们提供了动态SQL,可以让我们根据具体 ...
- 使用mpvue开发小程序教程(五)
在上一章节中,我们了解了组件的三个基本特性以及组件的基本使用方法.在实际的小程序开发中,我们应该以组件的思维去设计每个小程序的功能页面,对其进行合理的组件拆分,让每个部分都保持功能简洁.条理清楚.各司 ...
- .Net Core扩展 SharpPlugs简单上手
SharpPlugs .Net Core 鋒利扩展,这是本人的开源项目 地址是 GitHub地址 大家喜欢 的话可以加个星哦 当前功能 DI AutoMapper ElasticSearch WebA ...
- 使用Flume消费Kafka数据到HDFS
1.概述 对于数据的转发,Kafka是一个不错的选择.Kafka能够装载数据到消息队列,然后等待其他业务场景去消费这些数据,Kafka的应用接口API非常的丰富,支持各种存储介质,例如HDFS.HBa ...
- JDBC设计理念浅析 JDBC简介(一)
概念 JDBC是J2EE的标准规范之一,J2EE就是为了规范JAVA解决企业级应用开发制定的一系列规范,JDBC也不例外. JDBC是用于Java编程语言和数据库之间的数据库无关连接的标准Java A ...