c++零碎知识点
来源:互联网 发布:农村网络消费研究报告 编辑:程序博客网 时间:2024/04/27 19:46
1. vector中的元素不可以是引用
引用不是对象,它只是为一个已经存在的对象所起的另外一个名字。
vector是对象的容器,而引用不是对象,因此组成vector的元素不能是引用。
2. 若要在在类外定义的某个类的inline成员函数,则要把定义写在和该类同一个头文件中,不要写在其他的源文件中,否则会造成链接错误
// ……class A{ void f();};// ……inline void A::f(){}
3. string与int转换
1. string转int
string str;int val = atoi(str.c_str());//atoi() 是C标准库中的一个函数
2. int转string
//方法一:int val = 1;char buf[10];_itoa_s(val, buf, 10);string s(buf);//itoa()是非标准C函数(部分编译器可以使用,跨平台最好不用)。三个参数分别是:要转换的int,目标字符串,转换基数(10:十进制;2:二进制……)
//方法二:#include <sstream>int val = 1;stringstream stream;stream << val;string str = steam.str();//使用string流
//方法三:#include<string>int val = 1;string str = to_string(val);//使用C++11新引入的to_string函数
4. 直接初始化、拷贝初始化
在初始化一个变量的时候,一般通过两种方式来初始化:
string s1("Hello World"); //直接初始化string s2 = "Hello World"; //拷贝初始化string s3(10, 'c'); //直接初始化
当初始化用到的值只有一个的时候,用这两种初始化的方式都可以;但如果像上面s3那样初始化要用到的值有多个,则一般来说只能用直接初始化。
5. explicit关键字
在一个类中,如果某个构造函数只接受一个实参,那么它实际上定义了一种类型转换机制,即从该构造函数的参数类型向该类的类型转换的隐式规则。
class A{ //... A() = default; //该构造函数实际上定义了一条从string类型转换到A类型的隐式规则 A(string s){}; void func(const A&){}; //...};
//这段代码可以通过编译A a;string str = "abc";//将string类型的str隐式转换成A类型之后,传入funca.func(str);
explicit关键字的作用就是阻止这种隐式转换的发生。
class A{ //... A() = default; //explicit阻止了由string类型向A类型的隐式转换 explicit A(string s){}; void func(const A&){}; //...};
//这段代码不能通过编译A a;string str = "abc";//错误:string构造函数是explicit的,不能转换成类型Aa.func(str);
explicit关键字只对一个实参的构造函数有效;
只能在类内声明构造函数时使用explicit关键字,在类外定义时不应重复;
explicit构造函数只能用于直接初始化,不能用于拷贝初始化。
string str = "abc";//正确,explicit构造函数只能用于直接初始化A a(str);//错误,explicit构造函数不能用于拷贝初始化A b = str;
6. 常量引用,指向常量的指针
- 常量引用仅对引用可参与的操作做出了限定,对于被引用的对象本身是否是一个常量未作限定。
- 指向常量的指针仅要求不能通过该指针改变所指对象的值,对所指的对象本身是否是常量未作限定。
//均可通过编译int i = 42;const int &r1 = i;const int *p1 = &i;const int j = 10;const int &r2 = j;const int *p2 = &j;
7. 顶层const,底层const
- 指针指向一个对象,同时指针本身也是一个对象。
- 顶层const表示指针本身是个常量,底层const表示指针所指的对象是一个常量。
- 更一般的,顶层const可以表示任意的对象是常量,这一点对任何数据类型都适用,而不仅限于指针。
- 底层const则与指针和引用等复合类型的基本类型部分有关。
- 指针类型既可以是顶层const,也可以是底层const。
- 用于声明引用的const都是底层const。
int i = 0;int *const p1 = &i; //顶层const, p1的值不可变const int ci = 42;const int *p2 = &ci; //底层const,p2的值可变const int *const p3 = p2; //靠右的const是顶层const,靠左的const是底层constconst int &r = ci; //用于声明引用的const都是底层const
8. 类的const成员函数
定义一个类A:
class A{public: string fuc() { return str; }private: string str;};
A a;a.func();
在调用成员函数时,实际上是在替对象a来调用它。
在调用成员函数时,成员函数通过一个名为this的额外隐式参数来访问调用它的那个对象,用请求该函数的对象的地址来初始化this.
//该例中,编译器把a的地址传递给func()的隐式形参this//调用过程相当于(伪代码):A::func(&a) //用&a来初始化this
this是一个指针,总是指向“这个”对象,所以this是一个常量指针,即不允许改变this中保存的地址
默认情况下,this是一个指向类类型非常两版本的常量指针,在该例中,this的类型是A *const。
//(伪代码)A::func(A *const this){ return this->str;}A::func(&a) //调用时用&a来初始化A *const
由于调用fun()时,fun()的形参this的类型是是A *const,那么就意味着这个this不能指向一个常量对象即const A. 也就是说,不能在一个常量A对象上调用成员函数func()
const A a2;a2.func(); //编译报错:error C2662: “std::string A::func(void)”: 不能将“this”指针从“const A”转换为“A &”
这时就可以引入const成员函数了,我们修改成员函数func()的声明:
class A{public: //将func()声明为const成员函数 string fuc() const { return str; }private: string str;};
const成员函数声明中,参数列表后面的const的作用是修改隐式this指针的类型,即,func()的隐式形参this的类型变为const A *const,即指向A类型常量对象的常量指针。
const A a3;A a4;a3.func(); //编译通过运行正确a4.func(); //编译通过运行正确//常量A类型对象和非常量A类型对象都可以调用func()了,提高了函数的灵活性//这里的调用相当于(伪代码)A::func(const A *const this){ return this->str;}A::func(&a3); //用&a3来初始化const A *constA::func(&a4); //用&a4来初始化const A *const
从这段代码中可以看到,将成员函数func()声明为const之后,无论是常量A对象,还是非常量A对象,都可以调用成员函数func()了,这在一定程度上提高了函数的灵活性。
另外,由于const成员函数中this是指向重点内容常量的指针,const成员函数不能改变调用它的对象的内容。
总结:
- 一个对象调用成员函数时,要先将自己的地址传入该成员函数,用于初始化该函数的隐式形参this
- const成员函数和非const成员函数的区别在于,某对象调用该成员函数时,传入该函数的隐式形参this的类型不同,一个是指向const对象的,一个是指向非const对象的
- 常量对象,常量对象的引用或指针,都只能调用const成员函数
- const成员函数不能够改变调用它的对象的内容
- 将成员函数声明成为const的有助于提高函数的灵活性
9. 静态成员的类内初始值
定义一个类:
class Employee{public: Employee() :id_(++number){}; Employee(const string &name) :name_(name), id_(++number){} string get_name() const{ return name_; } int get_id() const{ return id_; }private: //这样定义类内初始值的话会报错:error C2864: “Employee::number”: 带有类内初始值设定项的静态数据成员必须具有不可变的常量整型 //static int number = 0; //也就是说,类的static成员只有它是const的时候,才可以拥有类内初始值 //static const int number = 0; //这样是合法的定义 static int number;//声明而非定义 string name_; int id_;};
在使用时,需要先将number在源文件中定义一下(因为类内“static int number;”这一行只是声明了number成员而没有定义它)
/*class Employee之外的某个源文件*/int Employee::number = 0;
- C/C++零碎知识点
- C语言零碎知识点
- C/C++零碎知识点
- c 语言零碎知识点总结
- Object-C 零碎知识点笔记
- C语言中的零碎知识点
- C语言零碎知识点总结(结构体)
- 笔记 C语言零碎知识点记录
- C语言/ACM 零碎知识点及注意事项
- 零碎知识点
- 零碎知识点
- 零碎知识点
- 零碎知识点
- 零碎知识点
- 零碎知识点
- 零碎知识点
- 零碎知识点
- 零碎知识点
- PTA5-6 修理牧场(队列模拟哈夫曼树)
- 如何在Linux安装tree上
- Tarjan算法详解
- 观察者模式小结
- 解决:spark启动错误Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apach..
- c++零碎知识点
- 自定义字节流缓冲区
- DL学习笔记【19】nn包中的各位Modules
- 使用okHttp发起请求并用fastJson解析
- java学习笔记-04
- 最小二乘法
- 从零开始搭建一个简易的服务器(二)
- LeetCode 389. Find the Difference
- 有源蜂鸣器和无源蜂鸣器