C++类中的特殊成员函数示例详解
作者:tlanyan 发布时间:2023-11-07 13:02:08
前言
C++类中有几个特殊的非静态成员函数,当用户未定义这些函数时,编译器将给出默认实现。C++11前有四个特殊函数,C++11引入移动语义特性,增加了两个参数为右值的特殊函数。这六个函数分别是:
1、默认构造函数
默认构造函数指不需要参数就能初始化的构造函数。包含无参和所有参数有默认值两种类型的构造函数。
2、复制构造函数
复制构造函数指使用该类的对象作为参数的构造函数。可以有其他参数,但必须提供默认值。
3、复制赋值运算符
重载等号=,将该类的对象赋值给已定义对象。
4、析构函数
没啥可说的。
5、移动构造函数
C++11新增,该类的右值对象为参数的构造函数,其余同复制构造函数。
6、移动复制运算符
同复制赋值运算符,唯一不同是参数为右值。
看定义容易迷糊,上代码就会很清晰:
#include <iostream>
#include <string>
class Foo {
public:
std::string s;
// 默认构造函数
Foo() { std::cout << "default constructor" << std::endl; }
// 复制构造函数
Foo(const Foo& foo) { std::cout << "copy constructor" << std::endl; s = foo.s; }
// 复制赋值运算符
Foo& operator=(const Foo& foo) { std::cout << "copy assignment operator" << std::endl; s = foo.s; return * this;}
// 移动构造函数
Foo(Foo&& foo) { std::cout << "move constructor" << std::endl; s = std::move(foo.s); }
// 移动赋值运算符
Foo& operator=(Foo&& foo) { std::cout << "move assignment operator" << std::endl; s = std::move(foo.s); return *this;}
};
int main() {
Foo foo1;
Foo foo2(foo1);
foo1 = foo2;
Foo foo3(std::move(foo1));
foo2 = std::move(foo3);
}
用g++或者clang编译,加上-fno-elide-constructors -std=c++0x选项。执行程序输出如下:
default constructor
copy constructor
copy assignment operator
move constructor
move assignment operator
结果是我们预期的。需要注意的是Foo foo3 = foo1的形式会调用复制构造函数,不会调用复制赋值运算符。原因是Foo foo3 = xxx声明和定义一个新对象,而赋值是作用在已定义对象。移动赋值运算符同理。
C++11新增了=default和=delete函数修饰符,提示编译器使用默认或者删除默认的特殊函数。需要注意的是这两个修饰符只能修饰上述特殊函数,用户可以用其对特殊函数进行裁剪。一个例子:
struct Test {
// 使用默认构造函数
Test() = default;
// 删除复制赋值运算符
Test& operator=(const Test& test) = delete;
// 使用默认析构函数
~Test() = default;
};
参考
https://en.cppreference.com/w/cpp/language/member_functions
https://stackoverflow.com/questions/43349808/extended-lifetime-of-an-object-returned-from-function
来源:https://tlanyan.me/special-member-functions-in-cpp-class/
猜你喜欢
- CyclicBarrier 接着讲多线程下的其他组件,第一个要讲的就
- 什么是死锁我们先看看这样一个生活中的例子:在一条河上有一座桥,桥面较窄,只能容纳一辆汽车通过,无法让两辆汽车并行。如果有两辆汽车A和B分别由
- 一、抽象类是什么?在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的
- 什么是文件上传?文件上传就是把用户的信息保存起来。为什么需要文件上传?在用户注册的时候,可能需要用户提交照片。那么这张照片就应该要进行保存。
- 网上找了一些获取客户端IP的方法,但本地测试时,返回的是IPv6的表示方法"::1":Host文件里面:# &
- zenDiscovery实现机制ping是集群发现的基本手段,通过在网络上广播或者指定ping某些节点获取集群信息,从而可以找到
- Java 匿名内部类详解匿名内部类也就是没有名字的内部类正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写但使用
- 😎 先看效果一人分饰多角(bushi)😏 后端代码🍗 先引入websocket依赖<!-- websocket消息推送 -->&
- 二、简介多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力,但频繁的创建线程的开
- mybatis-plus依赖导入<dependency> <groupId>
- springboot集成 redispom文件<dependency> <groupId>
- 前言MyBatis提供了9种动态SQL标签:trim、where、set、foreach、if、choose、when、otherwise、
- 一直以为这个方法是java8的,今天才知道是是1.7的时候,然后翻了一下源码。这片文章中会总结一下与a.equals(b)的区别,然后对源码
- 关于logback日志的详解见这位仁兄的博客:Spring Boot-日志配置(超详细)我在这就开门见山直接介绍我们项目日志的配置使用吧!~
- AQS 同步队列1、AQS 介绍AQS 是 AbstractQueuedSynchronizer 的缩写,他是一个抽象同步类,为 JUC 包
- 前言Apache POI [1] 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Mi
- 为什么要在控制台输出 SQL 呢?当然是为了开发调试的时候方便了。如果一个 数据库相关的操作出现了问题,我们可以根据输出的SQL语句快速排查
- 前言最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Sc
- Spring Boot可以和大部分流行的测试框架协同工作:通过Spring JUnit创建单元测试;生成测试数据初始化数据库用于测试;Spr
- 什么是ShiroApache Shiro是一个功能强大且易于使用的Java安全框架,它执行身份验证、授权、加密和会话管理。借助Shiro易于