编译器给一个类默认生成的六个成员函数:
构造函数、析构函数、拷贝构造函数、赋值运算符重载、对象取地址运算符以及常对象取地址运算符。其中析构函数不能重载,默认的拷贝和赋值两个函数存在浅拷贝的问题。
对象取地址运算符重载和常对象取地址运算符重载如下:
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容。#include
using namespace std;class Person
{
public:Person* operator&(){return this;}const Person* operator&() const//这个const实际上是加到this指针前面了 this指针是 类型* const 指针常量{return this;}private:char m_name[10];int m_age;
};
1.引用和指针的区别
1. 引用在定义时必须初始化,指针没有要求 2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型 实体 3. 没有NULL引用,但有NULL指针 4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占 4个字节) 5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小 6. 有多级指针,但是没有多级引用 7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理 8. 引用比指针使用起来相对更安全 2.内联函数(加inline关键字),以空间换时间。声明为内联函数后编译器会在调用处对齐进行代码复制。直接将代码块在这里展开。减少了函数压栈(现场保护和现场恢复的时间)。 内联函数注意事项:1.内联只是一种建议,编译器会自己决定是否采纳。 2.内联函数不允许内部有循环和递归,它适用于调用次数多,代码简单的函数。 3.内联函数的的声明和定义一般都放在.h文件中,如果分开在头文件和源文件中会发生未定义的错误。引文内联函数的展开是在编译时完成的,链接会找不到。#include
using namespace std;inline void add(int a, int b)
{int c = a+b;
}int main()
{int a = 10,b=20;add(a, b);system("pause");return 0;
}
#include
#include"test.h"
using namespace std;int main()
{int a = 10,b=20;add(a, b);system("pause");return 0;
}
#include
using namespace std;
inline void add(int a, int b)
{int c = a + b;
}
上面为.h文件。
2.auto自动类型推导
auto声明的变量必须由编译器在编译时期推导而得。使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类 型。 1. auto与指针和引用结合起来使用 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加& 2. 在同一行定义多个变量 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。 注意事项:1.auto不能推导函数参数 2.auto不能推导数组#include
using namespace std;void test01()
{int a = 10;auto* ptr = &a;cout << typeid(ptr).name() << endl;auto& ref = a;cout << typeid(ref).name() << endl;
}void test02()
{int arr[5] = { 1,2,3,4,5 };auto br = arr;cout << typeid(br).name() << endl;//这里显示int *br[3] = 5;cout << arr[3] << endl;
}void test03()
{int arr[5] = { 1,2,3,4,5 };auto& br = arr;//数组的引用//int(&br)[5] = arr;//数组引用写法cout << typeid(br).name() << endl;//这里会显示int [5]不是int *br[3] = 5;cout << arr[3] << endl;
}int main()
{test03();system("pause");return 0;
}
3.基于范围的for循环
对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中 引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量, 第二部分则表示被迭代的范围。 注意:1. for循环迭代的范围必须是确定的 对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的 方法,begin和end就是for循环迭代的范围。#include
using namespace std;void test02(int array[])
{for (auto e : array)//数组传参传的是地址,不存在开闭范围,不能这样循环{cout << e;}for (int i = 0; i < sizeof(array) / sizeof(int); i++)cout << array[i];cout << endl;
}void test01()
{int br[] = { 1,2,3,4,5 };for (auto &e : br){e *= 2;cout << e;}cout << endl;for (int i=0;i
3.空指针,NULL在底层被宏定义为0和void*(无类型指针),它可以作为void*使用也可以作为整形0使用,默认情况下会被当作0,所以NULL在函数重载等情况下会造成不便。
在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void *)0。 1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引的。 2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。 3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。#include
using namespace std;void func(int i)
{cout << "func(int i)" << endl;
}void func(int* p)
{cout << "func(int* p)" << endl;
}void test01()
{cout << sizeof(nullptr) << endl;cout<
上一篇:如何快速创建vue的SPA项目
下一篇:力扣:珠玑妙算(详解)