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{publicstring 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;
0 0
原创粉丝点击