c++常见问题

14 篇文章 3 订阅

自己整理c++问题,都是我自己提出来然后自己找的答案其中也有我自己的理解如果有错误请联系QQ:1024275440
1.请写出1个预处理器编译指令:
2.预处理编译指令是以什么字符开头
3.Int main(int argc char*argv[])argc和argv[]分别代表什么意思
4.main程序运行成功和出现错误分别返回什么值
5.名称空间限定符的作用是什么
6.Using namespace声明的作用是什么
7.unsigned的作用是什么
8.typedef作用是什么
9.Const、Constexpr、enum的作用是什么如何进行使用
10.constexpr与函数类似为什么还要使用?
11.sizeof作用是什么
12.Unsigned int uint[10][10]总共有几行几列
13.动态数组vector需要引入的头文件是哪个
14.typename的作用是什么:
15.Not/And/Or/Xor代表符分别是什么:
16.重写和重载的区别是什么
17.如何声明内联函数,内联函数和普通函数有什么区别:
18.引用运算符解除引用运算符的作用是什么:
19.new和delete的作用是什么:
20.const用于指针有几种效果他们的作用有是什么:
21.const用于引用运算符有什么作用:
22.构造函数和析构函数的作用是什么他们有什么区别:
23.假设一个类叫做MemoryClass请写出他的复制构造,并且写出复制构造的作用:
24.请写出一个单例模式
25.this指针的作用是什么:
26.public/private/protected上述三种访问限定符的区别是什么:
27.私有继承和公有继承和保护继承的区别是什么:
28.请写出基类和派生类的构造顺序
29.如何向基类构造函数传递参数
30.派生类中如何调用基类的方法
31.使用什么关键字禁止继承
32.请写出一个指针多态和函数多态的例子:
33.请写出一个虚函数并说明虚函数的用途是什么:
34.什么是抽象类如何声明它们:(virtual abstractFunction()=0; )
35.override限定符的作用是什么:
36.关键字operator的作用是什么:
37.Std::unique_prt的作用是什么:
38.请写出4个C++类型转换运算符,并写出转换场景和转换例子:
39.请写出#ifndef和#endif的作用并写出使用场景:
40.#pragma once的作用是什么:
41.请用#define编写一个宏定义
42.Assert()的作用是什么:
43.Template关键字的作用是什么:
44.请写出一个包含默认参数的模板
45.模板具体的作用是什么应该如何将模板具体化
46.请写出四个顺序容器并说明特点
47.请写出八个关联容器并说明特点
48.请写出四个容器适配器并说明特点
49.STL有几类迭代器:
50.请写出五个STL算法
51.string和wstring的区别是什么:
52.string成员函数append()作用是什么:
53.String成员函数find()作用是什么请写出一个例子:
54.String成员函数erase()的作用是什么:
55…请用transform函数写出转换一个字符串为大写的例子:
56.std::string具体化了那个STL模板类:
57.vector末尾插入和中间插入有性能上的差别吗:
58.请写出const_iterator遍历vector例子:
59.deque与vector相比多出的函数是:
60.list常用函数:
61.假设类名为test属性包含有age、name,现在要求写出一个谓词函数用于list顺序容器sort排序
62.unordered set相较于set提供了那些函数:
63.make_pair的作用是什么:
64.map和multimap关联容器中first和second的作用是什么:
65.请写出一个智能指针例子:
66.请写出智能指针的类型:
-----------------------------------------------答案----------------------------------------------------------------

1.#include
2.#
3.Argc是参数个数,argv[]是命令参数
例子: cmd /c x.exe-a
Argc =2 argv[0]=x.exe argv[1]=a
4.运行成功返回0运行失败返回-1
5.如果编译器知道一个函数在两个地方,编译器无法判断要调用那个函数这会导致冲突无法编译因此就需要名称空间比如std::cout其中cout是std名称空间限定符的函数,这样就避免了如果有两个cout函数不知道调用那可以的情况。
6.Using namespace 的作用是简化名称空间限定符的使用,因为每次都使用名称空间限定符会显得程序比较容易冗余降低开发效率
例子:using std::cout
使用cout都是来自于std的命名空间中
Cout<<1
例子:using namespace std
使用cout默认使用std名称空间限定符
Cout<<1
7.unsigned用于声明有符号的变量
8.typedef作用是替换变量类型比如使用unsigned int改名 typedef unsigned int UINT,就可以改名为UINT主要是用于编写易于理解的代码
9.const常量声明该声明主要用于不改变的变量
constexpr常量函数与函数相比具有性能优化可以使用简单if、switch等结构,但是并非肯定被优化,主要用于计算使用
eunm主要用于声明固定的取值,且eunm声明的值是无法被修改的,应用场景比如彩虹的颜色,人的性别,是否结婚,是否死亡
10.constexpr是常量表达式与函数相比编译器可以进行优化可以使用if、switch结构
11.sizeof用于确定变量的长度,变量长度是指编译器将预留多少内存给变量
12.1010=100
13.vector需要引入#include
14.typenam是用于模板类中声明或依赖的类型名
15.not~ and& or| xor^
16.函数重载:名称和返回值相同,但是参数不同成为重载
函数重写:外壳不变即名称返回值形参不变但是实现逻辑改变(在父类和子类中使用虚函数)
17.inline关键字声明内联函数inline的作用是编译器将函数不转化为call而是就地展开
对于简单的函数功能使用inline内联函数可以大大加快函数运行速度,如果函数比较复杂可能不会有较大提升并引发其他问题。
18.引用运算符&用于获取变量的地址即变量的起始位地址,解除引用运算符
作用是访问指定地址的数据
19.new是动态的分配内存delete是释放内存比如int test=new int(100);这段代码就是开辟了一段动态内存可以理解为创建了一块堆,堆不由操作系统回收需要程序员手动回收否则在程序关闭的时候由垃圾回收机制回收,手动清除这段堆使用的代码就是delete,比如delete test
20.
Int * const test1=&test;
第一种方式:指针指向的地址不能改变但是可以修改指向的数据
Const int test1=&test;
第二种方式:指针指向的地址可以改变但是不能修改指向的数据
Const int
const test1=&test;
第三种方式:指针指向的地址不可以修改指向的数据也不可以修改
21.const用于引用运算符的作用是确保数据不会被改变
22.构造函数即类名()主要用于实例化对象时被调用,析构函数即~类名()作用是类对象销毁时调用
23.MemoryClass(MemoryClass &mem),复制构造在发生复制的时候会触发该函数比如一个函数传入的形参是MemoryClass memclass那么传入的memclass就会触发复制构造,复制构造的主要作用是方式类里面的指针被重复的析构函数清除后被访问导致错误,因为析构函数在清除指针变量后,指向的内容消失了但是指针还有地址。
24.
#include
using namespace std;
class Demo {
private:
Demo() {}
static Demo
demo;
public:
static Demo * GetClassDemo() {
if (demo == nullptr) {
demo = new Demo();
}
return demo;
}
};
Demo* Demo::demo = nullptr;
int main() {
Demo *d = Demo::GetClassDemo();
cout << d << endl;
}
25.this指针等同于&object他是当前对象的地址
26.Public是公共的任何类和函数可以访问,private是私有访问限定符出了自身可以访问任何类和函数不可以访问,protected是保护的访问修饰符准许派生类和友元类访问他
27.
Protected:准许派生类和友元类访问
Private:基类所有的公有程序都是私有的不能从外部访问
Public:按基类默认值访问
28.基类构造 、派生类构造、派生类析构、基类析构
29.
派生类名():基类(){}
30.
使用名称空间限定符基类::函数
31.final修饰只能是继承基类的派生类才可以
例子:
Class test final:public demo{}
32.
#include
#include
using namespace std;

class Fish {
public:
virtual void show() { cout << “Fish” << endl; };

};

class Cat:public Fish {
public:
void show() override { cout << “Cat” << endl; }

};

class Dog:public Fish {
void show() override { cout << “Dog” << endl; }

};
int main() {
Fish* f = new Cat();
f->show();
Fish* d = new Dog();
d->show();
}
33.
virtual虚函数关键字,虚函数主要是确保编译器调用覆盖版本不默认使用基类版本,比如假设基类叫做Fish派生类叫做Tuna 创建一个Tuna实例叫做t 那么Fish fish=&Tuna这个时候使用fish会调用基类下面的函数假如派生类和基类都有一个叫做GetClass的函数那么fish将调用基类的GetClass方法就算给他的是派生类引用,virtual虚函数就确保了编译器如果有覆盖版本优先调用覆盖版本virtual修饰了基类的GetClass方法那么fish.GetClass()调用的就是Tuna版本因为Tuna派生类的版本是覆盖版本
为什么要使用虚函数virtual?
因为如果是Fish
fish=&Tuna之后delete fish;会导致一个严重的问题,那就是fish释放只会走基类的析构函数不会走派生类的析构函数。
34.抽象类使用了virtual关键字比如基类有一个函数叫做show那么将他声明为抽象类即纯虚函数:virtual void show()=0;需要注意的是有=0这个表达式,声明的纯虚函数派生类必须实现这个纯虚函数。
35.override是一种检查限定符用来检查
1.基类函数是否为虚函数
2.基类中对应虚函数的特征是否与派生类中被声明为override的函数完全相同
36.operator运算符重载函数
例子:
class Data{
public:
int formatData[3];
public:
void pushData(int yyyy,int mm,int dd) {
formatData[0] = yyyy;
formatData[1] = mm;
formatData[2] = dd;
}
int * popData(){
return formatData;
}
public:
Data& operator ++() {
formatData[0]=+1;
return *this;
}
};
37.std::unique_ptr是智能指针类
声明一个智能指针的例子:unique_ptr dem(new int);
*demo=20;
智能指针与普通指针相比,除了能够在指针离开作用于后释放占用的内存。
38.
(1) static_cast
char a = ‘a’;int b = static_cast(a);
//正确,将char型数据转换成int型数据
double *c = new double;void d = static_cast<void>©;
//正确,将double指针转换成void指针
int e = 10;const int f = static_cast(e);
//正确,将int型数据转换成const int型数据
const int g = 20;int h = static_cast<int>(&g);
//编译错误,static_cast不能转换掉g的const属性
if(Derived *dp = static_cast<Derived >(bp)){//下行转换是不安全的
//使用dp指向的Derived对象 }else{
//使用bp指向的Base对象 }
if(Base
bp = static_cast<Derived *>(dp)){//上行转换是安全的
//使用bp指向的Derived对象 }else{
//使用dp指向的Base对象
}
(2) dynamic_cast 类似于static_cast是运行时检查但是资源耗费很大
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换(cross cast)。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。dynamic_cast是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。
(3) reinterpret_cast
(4) const_cast
Static_cast例子: static_cast用于相关类型指针之间进行转换,可以进行向上转型和向下转型
#include
#include
#include<Windows.h>
using namespace std;

class Fish {
public:
void show() {
cout << “Fish” << endl;
}
};

class Cat final :public Fish {
public:
void show() {
cout << “Cat” << endl;
}
};
int main() {
Fish* fishTest = new Cat();
fishTest->show();
Cat* catTest = static_cast<Cat*>(fishTest);//向下转型
catTest->show();
}
Static_cast只会检查类型是否相关不会执行任何运行阶段检查
dynamic_cast会在执行阶段进行检查只有基类声明有virtual关键字的多态方法才行
reinterpret_cast准许不相关类型的转换通常用于static_cast不也许的转换,主要用于低级程序比如说驱动程序例子:
classDemo demo=new classDemo();
unsigerd char
byteFoAPI=reinterpret_cast<unsigerd char*>(demo)
这里的unsigerd char指的是byte数组,尽量不适用reinterpret_cast转换因为不安全除非万不得已
const_cast可以让程序员关闭对象访问修饰符const
例子:
Void DisplayAllData(const SomClass
data){
SomClass * pCasteData=const_cast<SomClass*>(data);
pCastedData->DisplyMembers();
}
39.#ifndef是一个条件处理指令,让预处理器仅在标识符未定义的时候才继续
#endif告诉预编译器,条件处理指令到此结束
主要用来检查是否重复包含,如果头文件第一次编译则肯定是没有定义的因此#ifndef继续执行编译例子:
#ifndef HEADER1
#define HEADER1
#include<header2.h>
class demo1(){
}
#endif
结束
#ifndef HEADER2
#define HEADER2
#include<header1.h>
Class demo2{

};
#endif
上述例子中head1包含了head2,head2包含了head1他们互相包含这是非常危险的因为这会导致编译器的递归问题因此需要使用#ifndef #endif
40.#pragma once是和#ifdef #endif类似是避免重复包含
41.#define demo(x)((x)*(x))
#define MAX(a,b)((a)>(b)?(a):(b))
42.assert用于检查是否符合出现问题需要头文件<assert.h>
43.template模板声明语法,template包含typename关键字它定义了模板参数
例子template
ObjectType getMax(ObjectType t1,ObjectType t2) {
if (t1 > t2) {
return t1;
}
return t2;
}
int main(){
Std::cout<<getMax(10,20)<<std::endl;
}
例子:
template<typename T1,typename T2=T1>
int FunctionInt(T1 t1, T2 t2) {
return t2;
}
int main(){
Std::cout<<FunctionInt<int,double>(10,20.5)<<std::endl;
}
template模板函数也可以不指定类型
44.templatee
45.Template模板是创建类的蓝图,在编译器看来仅当模板以某种方式使用后,其代码才存在,换言之定了但没有使用的模板类会被编译器忽略,可以通过模板参数来实例化模板类
例子:
template
void show(T t) {
cout << t << endl;
}
template<>void show(int i) {
cout << “模板具体化” << endl;
cout << i << endl;
}
int main() {
float f = 10.6f;
int i = 10;
show(f);
show(i);
}
如果不将模板具体化int形参那么在不适用模板的情况下编译器将不产生任何模板代码。
46.
std::vector:与动态数组类似,在最后插入数据可将vector视为书架可以从两端添加和拿走数据
Std::deque:与vector类似,但是只也许在开头插入或删除元素
Std::list:操作与双链表一样,可以将它视为链条,对象被链接在一起,你可以在任何位置添加或删除对象
Std::forward_list类似于list但是为单链表,只能从一个方向遍历
47.
std::set 存储各不相同的值,在插入时进行排序,容器复杂度为对数
Std::unordered_set:存储各不相同的值,在插入时进行排序,容器复杂度为常数
Std::map:键值对存储对唯一键进行排序
Std::unordered_map:类似于map
Std::multiset类似于set但是值可以不唯一
Std::unordered_multiset:类似于multiset
Std::multimap:类似于map但是不要求键唯一
Std::unordered_multimap:类似于unordered_map不要求键唯一
48.
Std::stack:以LIFO后进先出的方式入栈类似于栈
Std::queue以FIFO先进先出的方式存储元素
Std::priority_queue特定顺序存储
49.
前向迭代器:这是输入迭代器和输出迭代器的一种细化,它准许输入和输出,向前迭代器通常用于单链表
双向迭代器:这是一种向前迭代器的细化,可以执行递增递减的操作,双向迭代器通常用于双链
随机迭代器:这是双向迭代器的细化,可以将其加减一个偏移量,还可以将两个迭代器相减得到集合中两个元素的相对距离,随机迭代器主要用于数组。
50.
Std::find 在集合中查找值
Std::find_if;根据用户指定的谓词在集合中查找值
Std::reverse:反转集合中元素的排列顺序
Std::remov_if:根据用户定义的谓词将元素从集合中删除
Std::transform:使用用户定义的变换函数对容器的元素进行变换
51.string是操纵简单字符串
wstring主要用于操作宽字符串
52.append()拼接字符串,也可以使用+=代替
53.String demo;
Demo.find(“要搜的字符”,从什么位置开始);如果找到返回下标,没有找到返回nops即宏定义的-1
54.string demo; demo.erase(删除字符的下标,要删除多少字符);erase()函数用于截断字符串需要头文件#include
55.std::basic_string的具体化.
56.Vector中间插入或删除所需时间与该元素后面的个数成正比,末尾插入元素时间固定
Push_back()末尾插入
Insert()在指定位置插入
57.vector v;
v.push_back();在末尾插入元素v.pop_back()在末尾移除元素
58.
vectorvectorInt = { 100,200,300,400 };
vector::const_iterator element = vectorInt.cbegin();
while(element != vectorInt.cend()) {
std::cout << *element << std::endl;
element++;
}
59.deque也是动态数组类与vector相比deque支持头部插入而vector只能末尾插入,deque头部插入函数push_front和pop_front;
60.list顺序容器常用函数
(1)push_back();将元素添加到末尾
(2)push_front();将元素添加到头部
(3)begin();容器的起始地址也是第一个元素地址,end()最后的元素的地址
(4)erase();删除元素
(5)sort();对全部元素进行从小到大排序
(6)revese()反转元素排序默认从大到小
61.
Bool sortListClassTest(const test &t1,const test &t2){
Return(t1.age<t2.age);
}
ListlistTest;
listTest.push_back(xxxxxx);
listTest.sort(sortListClassTest);//使用谓词函数对类中age为首进行排序
62.
Unordered set比set多了一些统计函数比如:max_bucker_count()/load_factor()等等
63.
Make_pair是map或multimap关联容器insert插入元素中使用的例子:
Map<int,string>demo;
Demo.insert(make_pair(1,”张三”));
64.
first是键的值
second是对应的值
例子:
Map<int,string>dmo;
Demo.insert(make_pair(1,”张三”));
Demo.insert(make_pair(2,”李四”));
Map<int,string>::iterator element=demo.find(1);
Cout<<”KEY:”<first<<endl;
Cout<<”VAL:”<second<<endl;
65.
#include
using namespace std;
template
class Autopointer {
private:
T *typeT;
public:
Autopointer(T *pdata) {
cout << “构造函数被使用” << endl;
typeT = pdata;
}
~Autopointer() {
if (this->typeT != nullptr) {
cout << “指针已被销毁” << endl;
delete typeT;
}
}
Autopointer(Autopointer &classPointer) {
cout << “复制构造被使用” << endl;
}
T operator *() const{
cout << “*被使用” << endl;
return *(typeT);
}
T operator->() {
cout << “->被使用” << endl;
return typeT;
}
};
template
void copyPoint(Autopointer const &data) {
cout << *data << endl;
}
int main() {
AutopointeruInt(new unsigned int(1000));
cout << *uInt << endl;
copyPoint(uInt);
Autopointercopy = uInt;
}
66.深复制、写时复制、引用次数、引用链接、破坏性复制
67.operator

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虚构之人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值