1 基础(9)
new/delete会调用构造/析构函数,适合于类类型对象的创建与销毁。 关闭函数的类型自动转换(防止隐式转换)。 不是,两个不同类型的指针之间可以强制转换(reinterpret_cast)。1)C++中有malloc/free,为什么还需要new/delete?
2)C++中explicit关键字的作用?
3)C++中static关键字的作用?
4)C++中const修饰函数返回值时的作用是什么?
5)说一下C++里是怎么定义常量的?常量存放在内存的哪个位置?
6)说一下++i和i++的区别。
7)++i和i++的实现?
1 int& int::operator++ (){
2 *this +=1;
3 return *this;
4 }
1 const int int::operator++(int) {
2 int oldValue = *this;
3 ++(*this);
4 return oldValue;
5 }
8)举例说明深拷贝的安全性。
9)C++是不是类型安全的?
2 面向对象(15)
默认构造函数、析构函数、复制构造函数、赋值函数。 重载:在相同作用域中存在多个同名的函数,这些函数的参数表不同; 重写:派生类重新定义基类虚函数。 全局对象的构造函数。 当类中含有const、reference成员变量;基类的构造函数。 函数返回值采用引用传递的场合并不多,一般只出现在类的赋值函数中,目的是为了实现链式表达。例如: 面向过程:分析出解决问题所需要的步骤,然后用函数依次实现这些步骤,使用的时候依次调用;性能比面向对象高,但维护成本高。 面向对象:将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据;借助于封装、继承、多态性等特性,后期维护成本更低,更方便复用和扩展,但性能较差。 new operator实际上先后调用了operator new和constructor两个函数。 空类占用内存空间:1字节 基类构造函数。如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序,而不是它们在成员初始化表中的顺序。 成员类对象构造函数。如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序,而不是它们出现在成员初始化表中的顺序。 派生类构造函数。 对于纯虚函数来说,我们其实是可以给它提供实现代码的,但是由于抽象类不能实例化,调用这个实现的唯一方式是在派生类对象中指出其class名称来调用。 A 访问权限: public: 可以被该类中的函数、子类的函数、其友元函数访问,也可以由该类的对象访问 protected: 可以被该类中的函数、子类的函数、以及其友元函数访问,但不能被该类的对象访问 private: 只能由该类中的函数、其友元函数访问,不能以任何其他方法访问,该类的对象也不能访问 B 继承方式: public: 父类中的方法属性不发生改变; protected: 父类的public方法在子类中变为protected,其他方法不变; private: 父类的所有方法在子类中变为private。 不可。在构造函数中发生异常,控制权将转出构造函数之外。例如,在对象b的构造函数中发生异常,对象b的析构函数不会被调用,因此会造成内存泄漏;如果异常从析构函数抛出,而没有在当地进行捕捉,那个析构函数便是执行不全的。1)C++空类默认有哪些成员函数?
2)重载(overload)和重写(override)的区别
3)main函数执行之前会执行什么?
4)有哪几种情况初始化方式只能用initialization list而不能用assignment?
5)举例说明函数返回值采用引用传递的作用。
class A {
A& operator = (const A& other); // 赋值函数
};
A a, b, c;
a = b = c; // 合法
(a = b) = c; // 非法
6)为什么拷贝构造函数必需是引用传递,不能是值传递?
7)析构函数一般写成虚函数的原因?
8)面向过程与面向对象的区别?
9)new operator 和operator new 的区别?
10)重写函数的访问修饰符是可以不同的,例如尽管virtual中是private的,派生类中重写可以改为public。
11)空类是否占用内存空间?占用多少?
12)构造函数调用顺序?
13)纯虚函数可以实现吗?如果实现,有什么实际意义或者说如何调用?
14)说说public、protected、private区别。
15)构造函数析构函数可否抛出异常?
1)C++的四种强制转换?
C++的四种强制转换包括:static_cast, dynamic_cast, const_cast, reinterpret_cast
static_cast:明确指出类型转换,⼀般建议将隐式转换都替换成显式转换,因为没有动态类型检查,上行转换(派⽣类->基类)安全,下行转换(基类->派⽣类)不安全,所以主要执行非多态的转换操作;
dynamic_cast:专门用于派生类之间的转换,type-id必须是类指针、类引⽤或void*,对于下行转换是安全的,当类型不⼀致时,转换过来的是空指针,而static_cast,当类型不⼀致时,转换过来的是错误意义的指针,可能造成⾮法访问等问题。
const_cast:专门⽤于const属性的转换,去除const性质,或增加const性质,是四个转换符中唯⼀⼀个可以操作常量的转换符。
reinterpret_cast:不到万不得已,不要使用这个转换符,高危操作。使⽤特点:从底层对数据进⾏重新解释,依赖具体的平台,可移植性差;例如可以将整型转换为指针,也可以把指针转换为数组;可以在指针和引⽤之间进⾏肆无忌惮的转换。
1) vector与deque的区别?
1)deque访问容器元素的效率比vector容器慢很多;
原因在于deque要跨内存块来访问,而vector只是使用一个内存块,不用跨内存的操作。vector容器相当于一个可以动态分配的数组。
2)扩充容器容量的方面deque比vector的效率高很多;
deque是申请一个小的内存块,然后把新申请的内存块与其它的deque内存块整合起来。
vector是申请一个比原先更大的新内存块,把原vector里面的数据复制到新的大内存块里面,然后销毁原先的内存块。所以,在容量扩充方面,deque比vector高效,而且内存利用率也高。
3)vector不可以收缩,deque自动收缩;
vector不支持把容器的容量调小的操作,即容量需求小于实际容量的情况不会有任何操作。而deque因为它是有很多小内存块的组成的,所以有空闲的内存块时,会销毁空闲的内存块,但不会影响deque里面已有的数据。
2) vector方法push_back与emplace_back的区别?
push_back()向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而emplace_back()在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
3) 有指针为什么还要迭代器(STL迭代器的作用)?
迭代器把不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构也可以达到循环遍历集合的效果。
迭代器不是指针,是类模板,只是表现的像指针。它只是模拟了指针的⼀些功能,通过重载指针的⼀些操作符,如->、*、++、--等。迭代器封装了指针,是⼀个“可遍历STL(Standard Template Library)容器内全部或部分元素”的对象,本质是封装了原⽣指针,是指针概念的⼀种提升(lift),提供了⽐指针更高级的⾏为,相当于⼀种智能指针,他可以根据不同类型的数据结构来实现不同的++,--等操作。迭代器返回的是对象引⽤⽽不是对象的值,所以std::cout只能输出迭代器使⽤*取值后的值而不能直接输出其自身。