C++
变量和基本变量类型
const限定符
const对象在定义时必须初始化,默认情况下const变量仅在文件内有效。如需多个文件共享,则要加extern关键字。
const的引用
const int ci = 1024;
const int &r1 = ci;
允许常量引用绑定非常量对象,常量引用可以直接赋值,常量引用不能给非常量引用赋值。
int i = 42;
const int &r1 = i;//可以
const int &r2 = 32;//可以
int &b = r1*2;//不可以
指向常量的指针
指向常量的指针(pointer to const)不能改变其所指对象的值。普通指针不能指向const变量,但是ptc可以指向非const变量,指向非const变量的ptc不能改变该对象的值。总之,ptc不能改变任何变量
常量指针
常量指针一旦完成初始胡,它的值(存放在指针中的地址)就不能改变了,能否改变指向的数据取决于它所指向的值的类型。
int errNumb = 0;
int *const curErr = &errNumb;//curErr将一直指向errNumb,可以改变errNumb的值
const double pi = 3.14159;
const double *const pip = π//pip是一个指向常量对象的常量指针,不能改变pi的值
引用必须被初始化,一旦初始化完成,引用将和它的初始值对象绑定在一起,无法再绑定到其他对象。
面向对象程序设计
拷贝构造函数的第一个参数必须是一个引用类型,拷贝构造有两种:深拷贝、浅拷贝。当出现类的等号赋值时,会调用拷贝函数,在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。所以,这时,必须采用深拷贝。
深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。简而言之,当数据成员中有指针时,必须要用深拷贝。
https://www.cnblogs.com/alantu2018/p/8459250.html
关于拷贝构造函数的问题:
1.为什么拷贝构造函数必须是引用传递,不能是值传递?
简单的回答是为了防止递归引用。
具体一些可以这么讲:
当一个对象需要以值方式传递时,编译器会生成代码调用它的拷贝构造函数以生成一个复本。如果类A的拷贝构造函数是以值方式传递一个类A对象作为参数的话,当 需要调用类A的拷贝构造函数时,需要以值方式传进一个A的对象作为实参; 而以值方式传递需要调用类A的拷贝构造函数;结果就是调用类A的拷贝构造函数导 致又一次调用类A的拷贝构造函数,这就是一个无限递归。
2.拷贝构造函数的作用。
作用就是用来复制对象的,在使用这个对象的实例来初始化这个对象的一个新的实例。
3.参数传递过程到底发生了什么?
归根结底是值的传递,如果是指针或引用,实际传递的是地址。
4.类中有指针数据成员时,拷贝函数的使用?
需要显式地定义拷贝构造函数,否则如果采用编译器生成的默认拷贝构造函数,仅仅只是赋值指针指向的地址值,并没有重新分配空间。
5.判断拷贝构造函数。
对于一个类X,构造函数的第一个参数是下列之一:
a)X&
b)const X&
c)volatile X&
d)const volatile X&
且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数。
6.类中可以存在多个拷贝构造函数吗?
可以
class X {
public:
X(const X&); // const 的拷贝构造
X(X&); // 非const的拷贝构造
};
C++构造函数以及析构函数的若干面试问题
Q1:构造函数能否重载,析构函数能否重载,为什么?
A1:构造函数可以,析构函数不可以。
Q2:析构函数为什么一般情况下要声明为虚函数?
A2:虚函数是实现多态的基础,当我们通过基类的指针去析构子类对象时候,如果不定义成虚函数,那只调用基类的析构函数,子类的析构函数将不会被调用。如果定义为虚函数,则子类父类的析构函数都会被调用。
Q3:什么情况下必须定义拷贝构造函数?
A3:当类的对象用于函数值传递时(值参数,返回类对象),拷贝构造函数会被调用。如果对象复制并非简单的值拷贝,那就必须定义拷贝构造函数。例如大的堆栈数据拷贝。如果定义了拷贝构造函数,那也必须重载赋值操作符。
STL常用函数
std::find
输入参数可以是指针,也可以是迭代器
find(头指针,尾指针,要找的元素)
find(v.begin(),v.end(),要找的元素)
若查找失败,则返回尾指针或v.end()
int myints[] = { 10, 20, 30, 40 };
int * p;
p = std::find (myints, myints+4, 30);
std::vector<int> myvector (myints,myints+4);
std::vector<int>::iterator it;
it = find (myvector.begin(), myvector.end(), 30);