C++一个容易让人困扰的就是编译器会自动生成一些默认的特殊类成员函数,问题是这些默认的类成员函数到底是干吗的?里面是什么代码呢?,这时候我们可以通过Compiler Explorer等看它汇编生成代码。当然我们并不需要懂汇编代码,只看基本的框架就行。
进入正题前,可以复习一下这些默认生成的特殊成员函数。
class A
{
public:
// 默认构造函数;
A();
// 默认拷贝构造函数
A(const A&);
// 默认析构函数
~A();
// 默认重载赋值运算符函数
A& operator = (const A&);
// 默认移动构造函数
A(A&&);
// 默认重载移动赋值操作符
A& operator = (const A&&);
};
一、默认构造函数和默认析构函数:
我们在 Compiler Explorer 的左边 的左边,输入以下代码,让它生成汇编代码。(后面都是这样操作)
#include <string>
class student
{
private:
int age;
};
int main()
{
student s;
}
按c++标准,这里编译应该会生成一个student默认的构造函数还有析构函数,但是你发现,什么都没生成阿?对的,这个类没必要生成什么默认构造函数,也没有什么要释放的内存的地方。但是我们加上这一行代码:
#include <string>
class student
{
private:
int age;
std::string name;//新加的
};
int main()
{
student s;
}
汇编代码如下:
我们发现,行1 就是生成的默认构造函数,在构造函数中,行9,调用成员变量 name 这个类(std::string)的默认构造函数。行13 是生成析构函数,在里面行21处,调用成员变量 name (std::string)的析构函数。
二、默认拷贝构造函数:
输入以下代码:
#include <string>
class student
{
public:
student(int _age,std::string _name):age(_age),name(_name){
}
private:
int age;
std::string name;
};
int main()
{
student s(10,"小明");
student s1 = s;
}
看一下汇编生成:
行32:就是编译器生成的拷贝构造函数。
三、默认移动构造函数
#include <string>
class student
{
public:
student(int _age,std::string _name):age(_age),name(_name){
}
private:
int age;
std::string name;
};
int main()
{
student s(10,"小明");
student s1 = std::move(s);
}
生成汇编代码:
student::student(student&&) [base object constructor]:
push rbp
mov rbp, rsp
sub rsp, 16
mov QWORD PTR [rbp-8], rdi
mov QWORD PTR [rbp-16], rsi
mov rax, QWORD PTR [rbp-16]
mov edx, DWORD PTR [rax]
mov rax, QWORD PTR [rbp-8]
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-8]
add rax, 8
mov rdx, QWORD PTR [rbp-16]
add rdx, 8
mov rsi, rdx
mov rdi, rax
call std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >::basic_string(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&) [complete object constructor]
nop
leave
ret
上面代码就是编译器生成的移动构造函数,其中:call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)
这个代码看着非常复杂,其实就是std::string的移动构造函数。(看上面最后的两个 &&就是典型的移动构造函数格式)
四、默认重载移动赋值函数
#include <string>
class student
{
public:
student(int _age,std::string _name):age(_age),name(_name){
}
private:
int age;
std::string name;
};
int main()
{
student s(10,"小明");
student s1(11,"SB");
s1 = std::move(s);
}
生成汇编代码:
student::operator=(student&&):
push rbp
mov rbp, rsp
sub rsp, 16
mov QWORD PTR [rbp-8], rdi
mov QWORD PTR [rbp-16], rsi
mov rax, QWORD PTR [rbp-16]
mov edx, DWORD PTR [rax]
mov rax, QWORD PTR [rbp-8]
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+8]
mov rax, QWORD PTR [rbp-8]
add rax, 8
mov rsi, rdx
mov rdi, rax
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)
mov rax, QWORD PTR [rbp-8]
leave
ret
上面代码就是编译器生成的默认重载移动赋值函数,其中: call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)
上面代码就是调用std::string的移动赋值函数。