C++面试题合集.C++基础系列

16.编写类String的构造函数、析构函数和赋值函数,已知类String的原型为:

指针 与 引用有什么差别?

引用就是C++对C语言的重要扩充。引用就是某一变量的一个别名,对引用的操作与对变量直接操作完全一样。引用的声明方法:类型标识符 &引用名=目标变量名;引用引入了对象的一个同义词。定义引用的表示方法与定义指针相似,只是用&代替了*。

1.指针有自己的一个地址空间,但是引用只是变量的一个别名
2.Sizeof()结果不同,指针调用sizeof()后为4,引用调用sizeof后结果为变量的大小
3.初始化不同,指针可以初始化为nullptr,引用定义的时必须初始化为一个变量的引用
4.++运算的含义不同,指针++地址指向下一个,引用++是变量的值加一
5.指针的指向可以改变,引用只能是一个变量的引用,不可以改变,指向不可改变,引用可以理解成一个常量指针
6.可以有const指针,不可以有const引用
7.参数传递是,指针需要解引用才能对变量进行操作,直接对引用的修改就是对变量的修改
8.指针可以有二级指针,引用不可以
9.如果返回一个动态分配的对象或内存,应该使用指针,而不是引用,引用容易产生内存泄漏

2.计算sizeof的值

Func(char str[100])函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,还失去了其常量特性,可以作自增、自减等操作,可以被修改。
数组名的本质:
1)数组名指代一种数据结构,这种数据结构就是数组;
Char str[10];
Cout<<sizeof<<endl;//10
2)数组名可以转换为指向其指代实体的指针,而且时一个指针常量,不能自增、自减操作,不能被修改
Char str[10]
Str++;//编译出错,提示str不是左值
3)数组名作为函数形参时,沦为普通指针。

14.编写一个函数,作用把一个char组成的字符串循环右移n个。比如原来时“abcdefghi”如果n=2,移位后应该时hiabcdefg

最频繁使用的库函数:strcpy,memcpy,memset
void memcpy( void dest, const void src, size_t count );
char
strcpy(char
dest, const char
src);
strcpy与memcpy区别:
1)复制的内容不同,strcpy只能复制字符串,memcpy可以复制任何内容,例如字符数组、整型、结构体、类等。Memcpy与memset配合使用
2)复制的方法不同。Strcpy不需要指定长度,它遇到被复制字符的串结束符以”\0”才结束,容易产生溢出。Memcpy根据3个参数巨顶复制的长度。
3)用途不同。通常复制字符串用strcpy,复制其他类型用memcpy。
代码见VS

17.const关键字有什么作用

1)想阻止一个变量被改变,可以使用const关键字。在定义const变量时,通常需要对它进行初始化,因为以后就没有机会区改变它了。
2)对指针来说,可以指定指针本身为const,也可以指定指针所指数据为const,或者二者同时指定为const.
3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值。
4)对的成员函数,若指定为const类型,表明是一个常函数,不能修改成员变量。
5)对于类的成员函数,有时候必须指定其返回值为const类型,以使其返回值不能为左值。
常函数
形式: void fun() const {}
构造函数和析构函数不可以是常函数
特点:①可以使用数据成员,不能进行修改,对函数的功能有更明确的限定;
②常对象只能调用常函数,不能调用普通函数;
③常函数的this指针是const CStu*.

20.static关键字作用(22,23)

1.全局静态变量
在全局变量前加上static关键字,就成为一个全局静态变量
在内存中的位置,静态存储区,在整个程序运行期间一直都存在
初始化:未经初始化的全局静态变量会被初始化为0(自动对象的值时任意的,除非他被显示的初始化)
作用域:全局静态变量在声明它的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾。
2.局部静态变量
在局部变量之前加上关键字,=》局部静态变量
内存中的位置:静态存储区,data segment或.bss段
初始化:未经初始化的全局静态变量会自动被初始化为0
作用域:局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,并没有销毁,而是任然驻留在内存当中。
3.静态函数
在函数返回类型前加static,函数就被定义为静态函数。函数的定义和声明在默认情况下都是extern的,但是静态函数只能在声明它的文件中可见,不能被其他文件所见所用。
函数的实现使用static修饰,那么这个函数只能在本cpp使用,不会痛其他cpp中的同名函数冲突。
Warning:在头文件声明的全局函数不要加static,在cpp内声明的全局函数需要加static(只供本cpp使用)。
4.类的静态成员
在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,保证了安全性。
静态成员是类的所有对象中共享的成员,不是某个对象的成员。
静态数据成员保存在静态存储区域,data segment或.bss段
5.类的静态函数
属于类的静态成员,不是对象成员。对静态成员的引用不需要对象名,类名::静态成员
在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员。如果静态成员函数中要引用非静态成员时,通过对象来引用(this-》静态成员)。

24.C++中四种cast转换

四种类型转换:static_cast,dynamic_cast,const_cast,reinterpret_cast
1)const_cast
用于将const常量转换为普通变量(非const变量)
2)Static_cast
用于各种隐式转换,比如非const转换为const,void*转换为指针等
Static_cast能用于多态向上转化,如果向下转能成功但不安全,结果未知。
3)Dynamic_cast
用于动态类型转换,只能用于含有虚函数的类,用与类层次之间的向上和向下转化。只能转指针或引用。
向下转化,如果时非法的对于指针返回nullptr;对于引用抛异常。
向上转换,指的时子类向基类转换
向下转换:指的时基类向子类转换。
4)Reinterpret_cast
几乎任何都可以转,但可能会出问题,尽量少用。
为什么不适用C的强制转换,因为强制转换不进行错误检查,容易出错。

29.数组和指针的区别

保存内容:指针保存数据的地址;数组保存数据
访问方式:指针间接访问数据,首先获得指针的内容,然后将其作为地址,从该地址获取数据;数组直接访问数据;
适应范围:指针通常用于动态数据结构;数组通常用于固定数目且数据类型相同的元素。
分配内存方式:指针通过malloc或new分配,free或delete释放;数组隐式的分配和删除。
指针通常指向匿名数据,操作匿名函数;数组自身为数据名。

27.C++中的四种智能指针(31,35)

C++里面包含4个智能指针:auto_ptr,shared_ptr,weak_ptr,unique_ptr;其中autor_ptr已经被C++11弃用,后面三个是C++11支持。

为什么要使用智能指针?
因为存在以下情况:申请的空间在函数结束时忘记释放,造成内存泄漏。使用智能指针可以很大程度上避免这种情况发生。
因为智能指针时一个类,当超出了类的作用域,类自动会调用析构函数,析构函数会自动释放资源。
智能指针的作用在函数结束时自动释放内存空间,不需要手动释放内存空间。

1.auto_ptr采用所有权模式
Auto_ptr p1 (new string(“I reigned lonely as a cloud”));
Auto_ptr p2;
P2=p1;//auto_ptr不会报错
此时不会报错,p2剥夺了p1的所有权,但是当程序运行时访问p1将会报错,所以auto_ptr的缺点时:存在潜在的内存崩溃问题。
2.Unique_ptr(替换auto_ptr)
Unique_ptr实现独占式拥有或严格拥有概念,保证同一时间只能一个智能指针可以指向该对象。他对于避免资源泄漏(new创建一个对象后忘记delete)特别有用。

采用所有权模式,还是上面的例子
Unique_ptr p3(new string(“auto”));
Unique_ptr p4;
P4=p3;//此时会报错
编译器认为p4=p3非法,避免了p3不再指向有效数据的问题。因此unique_ptr比auto_ptr更安全。
另外:当程序试图将一个unique_ptr赋值给另一个时,如果源unique_ptr是个临时右值时,编译器允许这么做;如果源unique_ptr将存在一段时间,编译器禁止这么做:
Unique_ptr pu1 (new string(“hello world”));
Unique_ptr pu2;
Pu2=pu1;//#1 not allowed
Unique_ptr pu3;
Pu3= unique_ptr(new string(“YOU”));//#2 allowed
其中#1会留下悬挂的unique_ptr(pu1),这可能导致危害。而#2不会留下悬挂的unique_pt,因为它调用unique_ptr的构造函数,该构造函数创建的临时对象在其所有权让给pu3后就会被销毁。
注意:如果想执行类似#1的操作,要安全的重用这种指针,可以给它赋新值。
C++有一个标准库函数std::move(),让你能够将unique_ptr赋值给另一个。
unique_ptr ps1, ps2;
ps1 = unique_ptr(new string(“hello”));
ps2 = move(ps1);
ps1 = unique_ptr(new string(“alexia”));
cout << (*ps2).c_str() << (*ps1).c_str() << endl;// hello alexia
3.Shared_ptr
Shared_ptr实现共享式拥有概念。多个智能指针以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放。资源可以被多个指针共享,它使用技术机制来表明资源被几个指针共享。可以通过成员函数use_count()来看资源的所有者个数。除了可以通过new来构造,还可以通过auto_ptr,unique_ptr,weak_ptr来构造。当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0,资源会被释放。
Shared_ptr是为解决auto_ptr在对象所有权上的局限性(auto_ptr是独占的),在使用引用计数的机制上提供了可以共享所有权的智能指针。
成员函数:
Use_count返回引用计数个数
Unique返回是否为独占所有权(use_count为1)
Swap交换两个shared_ptr对象(即交换所拥有的对象)
Reset放弃内部对象的所有权或拥有对象的变更,会引起原有对象的引用计数的减少
Get返回内部对象(指针),由于已经重载了()方法,因此和直接使用对象是一样的。Shared_ptr sp(new int(1));sp于sp.get()等价的。

4.Weak_ptr
Weak_ptr是一种不控制对象生命周期的智能指针,它指向一个shared_ptr管理的对象。进项行该对象的内存管理的是那个强引用的shared_ptr,weak_ptr只是提供了对管理对象的一个访问手段。
Weak_ptr设计的目的是为配合shared_ptr而引入的一种智能指针,它只可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用计数的增加或减少。
Weak_ptr是用来解决shared_ptr相互引用时死锁的问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会被释放。
他是对对象的一种弱引用,不会增加对象的引用计数,与shared_ptr可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数获得shared_ptr.

32.智能指针有没有内存泄漏的情况,怎么解决内存泄漏?智能指针是线程安全的码?

shared_ptr和unique_ptr的应用场景,unique_ptr是怎么实现的
智能指针的实现,weak_ptr为什么能解决循环引用的问题

30.什么是野指针,怎么规避

1.野指针与悬挂指针
访问一个已经销毁或访问权限受限的指针,访问一个不能访问的指针。野指针不能判断是否位NULL来避免。
悬挂指针:指针正常初始化,指向一个对象,但是等到对象销毁后,指针没有制空。悬挂指针就是指向了一个已经销毁了对象的指针。
2.产生原因
指针定义时没有初始化,指针会指向一个随机的内存地址空间
指针指向的内存空间释放后,指针的指向没有置空
指针操作超出变量作用域,不要返回指向栈内存对象的指针或引用,引用栈内存对象在函数结束的时候就会被释放。
3.危害
指针指向的内存空间已经销毁或访问受限,解引用一个非空无效指针是一个未定义的行为,报错不好定位。
4.怎么避免
定义指针的时候将其置为nullptr
指针指向的内存释放时,指针指向置为nullptr.

36.析构函数的作用,为什么要定义为虚函数,默认的为什么不是虚函数?

将可能被继承的父类的析构函数设置为虚函数,可以保证我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的内存,防止内存泄漏。
C++默认的析构函数不是时虚函数,因为虚函数需要额外的虚函数表和虚表指针,占用额外的空间。对于不会被继承的类来说,其析构函数如果时虚函数,就会浪费内存。所以只有当需要作为父类的时候,才设置为虚函数。

37.函数指针

定义:
函数指针时指向函数的指针变量
函数指针首先是个指针变量,该指针变量指向一个具体的函数。
c编译时,每一个函数都有一个入口地址,该入口地址就是函数指针指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数。
用途:
调用函数或做函数的参数,比如回调函数
示例:
Char* fun(charp){}//函数fun
Char
pf)(char p);//函数指针pf
Pf=fun;//函数指针指向函数fun
Pf§//通过函数指针pf调用函数fun
回调函数?

39.C++中析构函数的作用

析构函数与构造函数对应,当对象结束生命周期,如对象所在的函数已经调用完毕时,系统会自动执行析构函数。
析构函数名与类名相同,只是在函数名签名加一个位取反符~,以区别于构造函数。他不带任何参数,也没有返回值。只能由一个析构函数,不能重载。
如果用户没有编写析构函数,编译系统会自动生产一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器先调用自定义的析构函数再调用合成的析构函数),它不进行任何操作。
如果一个类由指针,在使用过程中动他分配了内存,那么最好显示构造析构函数,在销毁类之前,释放掉申请的内存空间,避免内存泄漏。
类析构顺序:1)派生类本身的析构函数;2)对象成员的析构函数;3)基类析构函数。

42.C++类成员的访问权限

成员访问限定符号:public,private,protected
用来控制类或者结构体成员变量和成员函数的访问权限
Public protected private
类的函数 可以 可以 可以
子类的函数 可以 可以 不可以
友元函数 可以 可以 可以
类的对象 可以 不可以 不可以

友元函数:可以是该类的友元函数,也可以是该类的友元类的成员函数。
如果声明不写 public、protected、private,则默认为 private。
类的函数可以访问public,protected,private成员
友元函数可以访问public,protected,private成员
子类的函数可以访问public,protected成员,不可以访问private成员。
类的对象只能访问public成员。
Public公有继承:
基类的私有成员,子类不可以访问;
基类的保护成员,子类可以继承为自己的保护成员,在派生类可以访问,在外部不可以访问。
基类的公有成员,子类可以继承为自己的公有成员,在派生类可以访问,在外部可以访问。外部只能访问public成员。
保护继承:
基类的公有成员和保护成员,子类继承为自己的保护成员,在派生类可以访问,在外部不可以访问,外部只能访问public成员。
基类的私有成员,子类不可以访问。
私有继承:
基类的公有成员和保护成员,子类继承为自己的私有成员,在派生类可以访问,在外部不可以访问。
基类的私有成员,子类不可以访问。
三种继承方式比较:
A类(基类) B类(A的派生类) C类(B的派生类)

公有继承 公有成员 公有成员 公有成员
私有成员 无 无
保护成员 保护成员 保护成员

私有继承 公有成员 私有成员 无
私有成员 无 无
保护成员 私有成员 无
保护继承 公有成员 保护成员 保护成员
私有成员 无 无
保护成员 保护成员 保护成员

43.C++中struct和class的区别

在C++中,可以用struct和class定义类,都可以继承。
区别:
Struct默认继承权限和默认访问权限是public,class的默认继承权和默认访问权限是private.
class还可以定义模板类形参,比如template<class T,int i>

50.什么时候会发生段错误
访问非法内存时会发生段错误:
使用野指针;
试图修改字符串常量的内容。

52.new和malloc区别

1)new分配内存按照数据类型进行分配,malloc分配内存按照指定子节数分配。
2)New返回指定对象的指针,malloc返回的void*,malloc的返回值一般都需要进行类型转化
3)New不仅分配一段内存,而且还会调用构造函数,malloc不会。
4)New分配的内存delete销毁,malloc则用free;delete销毁时会调用析构函数,而free不会。
5)New是一个操作符可以重载,malloc是一个库函数
6)Malloc分配的内存不够时,可以使用realloc扩容。扩容原理?
7)New如果失败了抛出bad_malloc异常,而malloc失败了返回nullptr
8)申请数组时:new[]一次性分配所有内存,多次调用构造函数,搭配使用delete[],delete[]多次调用析构函数,销毁数组钟的每个对象。而malloc只能sizeof(int)*n。

55.请你详细介绍一下C++11中的可变参数模板、右值引用和lambda这几个新特性。

可变参数模板
C++ 11的可变参数模板,对参数进行了高度泛化,可以表示任意数目、任意类型的参数,其语法为:在class或typename后面加上省略号
Template<class … T>
Void func(T … args)
{
Cout<<”num is”<<sizeof …(args)<<endl;
}
Func();//args不含任何参数
Func(1);//args包含一个int类型的实参
Fun(1,2.0);//args包含一个int一个double类型的实参
T叫做模板参数包,args函数参数包
省略号作用如下:
1)声明一个包含0到任意个模板参数的参数包
2)在模板定义的右边,可以将一个参数包展成一个个独立的参数
C++11可以使用递归函数的方式展开参数包,获得可变参数的每个值。通过递归函数展开参数包,需要提供一个参数包展开的函数和一个递归终止函数。
Using namespace std;
//最终递归函数
Void print()
{
Cout<<”empty”<<endl;
}
//展开函数
Template void print(head,Args… args)
{
Cout<<head<<”,”;
Print(args…);
}
Int main()
{
Print(1,2,3,4);
Return 0;
}
参数包args…在展开的过程中递归调用自己,每调用一次参数包中参数就少一个,直到所有参数都展开为止。当没有参数时,就会调用非模板函数printf终止递归过程。

右值引用
https://zhuanlan.zhihu.com/p/85668787
C++中,左值通常指可以取地址,有名字的值就是左值,而不能取地址没有名字的就是右值。
在C++11中,右值是由两个概念构成,将亡值和纯右值。
纯右值是用于识别临时变量和一些不跟对象关联的值,比如1+3产生的临时变量值;而将亡值通常是指具有转移语义的对象,比如返回右值引用T&&的函数返回值等。
C++11中,右值引用就是对一个右值进行引用的类型。由于右值通常不具有名字,所以我们一般只能通过右值表达式获得其引用,比如 T&& a=ReturnRvale();
假设ReturnRvalue()函数返回一个右值,那么上述语句声明了一个名为a的右值引用,其值等于ReturnRevalue()函数返回的临时变量的值。

基于右值引用可以实现转移语义和完美转发新特性
移动语义:
对于一个包含指针成员变量的类,由于编译器默认的拷贝构造函数都是浅拷贝,所有我们一般需要通过实现深拷贝的拷贝构造函数,为指针成员分配新的内存并进行内容拷贝,从而避免悬挂指针的问题。
#include
Using namespace std;

Class HasPtrMem{
Public:
HasPtrMem():d(new int(0)){
Cout<<”construct:”<<++n_cstr<<endl;
}
HasPtrMem(const HasPtrMem &h):d(new int(*h.d)){
Cout<<”copy construct:”<<++n_cptr<<endl;
}
~HasPtrMem(){
Cout<<”Destruct:”<<++n_dstr<<endl;
}
Int *d;
Static int n_cstr;
Static int n_dstr;
Statci int n_cpstr;
};
Int HasPtrMem::n_cstr=0;
Int HasPtrMem::n_dstr=0;
Int HasPtrMem::n_cptr=0;

HasPtrMem GetTemp() {
Return HasPtrMem();
}

Int main()
{
HasPtrMem a=GetTemp();
}

完美转发:
完美转发是指在函数模板中,完全依照模板的参数类型,将参数传递给函数模板中调用调用的另一个函数,即传入转发函数的是左值对象,目标函数就能获得左值对象,转发函数是右值对象,目标函数就是右值对象,而不产生额外的开销。
因此转发函数与目标函数参数一般采用引用类型,从而避免拷贝的开销。其次,由于目标函数可能需要能够既接受左值引用,又接受右值引用,所以考虑转发也需要兼容这两种类型。
C++11采用引用折叠的规则,结合新的模板推导规则实现完美转发。其引用折叠规则如下:
TR的类型定义 声明v的类型 v的实际类型
T& TR A&
T& TR& A&
T& TR&& A&
T&& TR A&&
T&& TR& A&
T&& TR&& A&&

因此,我们将转发函数和目标函数的参数设置为右值引用类型,
Void IamForwording(T &&t){
IrunCodeActually(static_cast<T &&>(t));
}

lambda表达式:
https://blog.csdn.net/sgh666666/article/details/89000215
Lambda表达式定义一个匿名函数,并且可以补捕获一定范围内的变量,其定义如下:
capturemutable->return-type{statement}
其中:
[capture]:捕获列表,捕获上下文变量以供lambda使用。同时[]是lambda演出服,编译器根据该符号来判断接下来代码是否是lambda函数。
(Params):参数列表,与普通函数的参数列表一致,如果不需要传递参数,则可以连通括号一起省略。
Mutable是修饰符,默认情况下lambda函数总是一个const函数,mutable可以取消其常量性,在使用该修饰符时,参数列表不可省略。
->return-type:返回类型是返回值类型
{statement}:函数体,内容与普通函数一样,除了可以使用参数之外,还可以使用所捕获的变量。
Lambda表达式与普通函数最大的区别是其可以通过捕获列表访问一些上下文中的数据。其形式如下:
[var]表示值传递方式捕捉变量var
[=]表示值传递方式捕捉所有父作用域的变量(包括this)
[&var]表示引用传递捕捉变量var
[&]表示引用传递捕捉所有父作用域的变量(包括this)
[this]表示值传递方式捕捉当前的this指针

Lambda的类型被定义为闭包的类,其通常用于stl库中,在某些场景下可用于简化仿函数的使用,同时lambda作为局部函数,也会提高复杂代码的开发加速,轻松在函数内重用代码,不必费心设计接口。

88.请问什么是大端小端以及如何判断大端小端

大端是指低字节存储在高地址;小端存储是指低字节存储在低地址。我们可以根据联合体来判断该系统是大端还是小端。因为联合体变量总是从低地址存储。

159.请你说一说你理解的虚函数和多态

多态的实现主要分为静态多态和动态多态
静态多态主要是重载,在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。举个例子:一个父类类型的指针指向一个子类对象时候,使用父类的指针去调用子类中重写了的父类中的虚函数的时候,会调用子类重写过后的函数,在父类中声明为加了virtual关键字的函数,在子类中重写时候不需要加virtual也是虚函数。
虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。

161.i++和++i的实现

++i实现
Int& int::operator++()
{
*this+=1;
Return *this;
}

I++实现
Const int int::operator(int)
{
Int old=*this;
++(*this);
Return old;
}

165.char的区别

Const char* arr=”123”
字符串保存在代码段的常量区,const本来是修饰arr指向的值不能通过arr去修改,但是字符串“123”在常量区,本来就不能改变,所以加不加const效果都一样
Char* brr=”123”
字符串123保存在常量区,跟arr指针指向的是同一个位置,同样不能通过brr去修饰“123”的值。
Const char arr[]=”123”
这里的123本来是在栈上,但是编译器可能会做某些优化,将其放在常量区
Char drr[]=”123”
字符串123保存在栈区,可以通过drr去修改。

184.重载与重写

重载:两个函数名相同,但是参数列表不同(个数,类型),返回值类型没有要求,在同一作用域中
重写:子类继承了父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数,这种情况是重写

189.STL基本组成

STL主要由:以下几部分组成:
容器、迭代器、仿函数、算法、分配器、配接器
他们之间的关系:分配器给容器分配存储空间,算法通过迭代器获取容器中的内容,仿函数可以协助算法完成各种操作,配接器用来套接适配仿函数
分配器–容器
算法,迭代器,容器
仿函数,算法
配接器,仿函数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

haimianjie2012

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

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

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

打赏作者

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

抵扣说明:

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

余额充值