一、c++中四种cast转换
C++中四种类型转换是:static_cast, dynamic_cast, const_cast, reinterpret_cast
1、const_cast
用于将const变量转为非const
2、static_cast
用于各种隐式转换,比如非const转const,void*转指针等, static_cast能用于多态向上转化,如果向下转能成功但是不安全,结果未知;
3、dynamic_cast
用于动态类型转换。只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。向下转化时,如果是非法的对于指针返回NULL,对于引用抛异常。要深入了解内部转换的原理。
向上转换:指的是子类向基类的转换
向下转换:指的是基类向子类的转换
它通过判断在执行到该语句的时候变量的运行时类型和要转换的类型是否相同来判断是否能够进行向下转换。
4、reinterpret_cast
几乎什么都可以转,比如将int转指针,可能会出问题,尽量少用;
5、为什么不使用C的强制转换?
C的强制转换表面上看起来功能强大什么都能转,但是转化不够明确,不能进行错误检查,容易出错。
二、C/C++ 中指针和引用的区别?
1.指针有自己的一块空间,而引用只是一个别名;
2.使用sizeof看一个指针的大小是4,而引用则是被引用对象的大小;
3.指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象 的引用;
4.作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引 用的修改都会改变引用所指向的对象;
5.可以有const指针,但是没有const引用;
6.指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能 被改变;
7.指针可以有多级指针(**p),而引用至于一级;
8.指针和引用使用++运算符的意义不一样;
9.如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄露。
三、smart pointer四个智能指针: shared_ptr,unique_ptr,weak_ptr,auto_ptr
https://www.cnblogs.com/shaonianpi/p/11179873.html
一、auto_ptr
auto_ptr这是C++98标准下的智能指针,现在常常已经被C++标准的其他智能指针取代。它的缺点是在转移所有权后会使运行期不安全。C++11新标准,用unique_ptr来代替auto_ptr原有功能,其用法介绍见第四部分unique_ptr。
#include <iostream>
#include <memory>
#include <string>
using namespace std;
void main(){
auto_ptr<string> country[5] =
{
auto_ptr<string>(new string("USA")),
auto_ptr<string>(new string("CHN")),
auto_ptr<string>(new string("RUS")),
auto_ptr<string>(new string("FRA")),
auto_ptr<string>(new string("GRB"))
};
auto_ptr<string> pwin;
pwin = country[2]; //将所有权从country[2]转让给pwin,此时country[2]不再引用该字符串从而变成空指针,在运行到循环时就会崩溃
for (int i = 0; i < 5; ++i)
cout << *country[i] << endl;//运行到[2]时崩溃,因为country[2]为空
cout << "The best is " << *pwin << endl;
system("pause");
}
二、share_ptr
share_ptr是C++11新添加的智能指针,它限定的资源可以被多个指针共享。
用法见下例:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
void fun(){
shared_ptr<string> pa(new string("CHN"));
shared_ptr<string> pb(new string("USA"));
cout << "*pa " << *pa << endl;//CHN
cout << "pa.use_count " << pa.use_count() << endl;//1
cout << "*pb " << *pb << endl;//USA
cout << "pb.use_count " << pb.use_count() << endl;//1
pa = pb;
cout << *pa << endl;//USA
cout << "pa.use_count " << pa.use_count() << endl;//2:pa和pb指向同一个资源USA了,该资源的计数为2,所以pb、pb都输出2
cout << "pb.use_count " << pb.use_count() << endl;//2
pa.reset();
pb.reset();
cout << "pa.use_count " << pa.use_count() << endl;//0
cout << "pb.use_count " << pb.use_count() << endl;//0
}
void main()
{
fun();
system("pause");
}
与数组相结合应用,见另一个例子:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
void main(){
shared_ptr<string> country[5] =
{
shared_ptr<string>(new string("USA")),
shared_ptr<string>(new string("CHN")),
shared_ptr<string>(new string("RUS")),
shared_ptr<string>(new string("FRA")),
shared_ptr<string>(new string("GRB"))
};
shared_ptr<string> pwin;
cout << pwin.use_count() << endl;//输出0
pwin = country[2];
/*使用shared_ptr时运行正常,因为shared_ptr采用引用计数,pwin和films[2]都指向同一块内存,
在释放空间时因为事先要判断引用计数值的大小因此不会出现多次删除一个对象的错误。
从名字share就可以看出了资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。
可以通过成员函数use_count()来查看资源的所有者个数。
*/
cout << pwin.use_count() << endl;//输出2
for (int i = 0; i < 5; ++i)
cout << *country[i] << endl;//对比auto_ptr,这里就不会崩溃,正常的输出所有的string字符串。
cout << "The best is " << *pwin << endl;
system("pause");
}
三、weak_ptr
weak_ptr是一种用于解决shared_ptr相互引用时产生死锁问题的智能指针。如果有两个shared_ptr相互引用,那么这两个shared_ptr指针的引用计数永远不会下降为0,资源永远不会释放。weak_ptr是对对象的一种弱引用,它不会增加对象的use_count,weak_ptr和shared_ptr可以相互转化,shared_ptr可以直接赋值给weak_ptr,weak_ptr也可以通过调用lock函数来获得shared_ptr。
先看一下两个shared_ptr指针互相引用导致的资源释放失败的例子:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class B;
class A
{
public:
shared_ptr<B> pb_;
~A()
{
cout << "A delete\n";
}
};
class B
{
public:
shared_ptr<A> pa_;
~B()
{
cout << "B delete\n";
}
};
void fun(){
shared_ptr<B> pb(new B());
cout << "pb.use_count " << pb.use_count() << endl;//1
shared_ptr<A> pa(new A());
cout << "pa.use_count " << pa.use_count() << endl;//1
pb->pa_ = pa;
cout << "pb.use_count " << pb.use_count() << endl;//1
cout << "pa.use_count " << pa.use_count() << endl;//2
pa->pb_ = pb;
cout << "pb.use_count " << pb.use_count() << endl;//2:由于share_ptr是共享资源,所以pb所指向的资源的引用计数也会加1
cout << "pa.use_count " << pa.use_count() << endl;//2
}//程序结束时,没有调用A和B的析构函数
void main()
{
fun();
system("pause");
}
而使用weak_ptr:把A中的shared_ptr<B> pb_改为weak_ptr<B> pb_weak,这样改为了弱引用,传递时不会增加pb引用计数use_count()的值,所以最终能够使A、B资源正常释放:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class B;
class A
{
public:
weak_ptr<B> pb_weak;
~A()
{
cout << "A delete\n";
}
};
class B
{
public:
shared_ptr<A> pa_;
~B()
{
cout << "B delete\n";
}
void print(){
cout << "This is B" << endl;
}
};
void fun(){
shared_ptr<B> pb(new B());
cout << "pb.use_count " << pb.use_count() << endl;//1
shared_ptr<A> pa(new A());
cout << "pa.use_count " << pa.use_count() << endl;//1
pb->pa_ = pa;
cout << "pb.use_count " << pb.use_count() << endl;//1
cout << "pa.use_count " << pa.use_count() << endl;//2
pa->pb_weak = pb;
cout << "pb.use_count " << pb.use_count() << endl;//1:弱引用不会增加所指资源的引用计数use_count()的值
cout << "pa.use_count " << pa.use_count() << endl;//2
shared_ptr<B> p = pa->pb_weak.lock();
p->print();//不能通过weak_ptr直接访问对象的方法,须先转化为shared_ptr
cout << "pb.use_count " << pb.use_count() << endl;//2
cout << "pa.use_count " << pa.use_count() << endl;//2
}//函数结束时,正确的情况下,应该调用A和B的析构函数
/*资源B的引用计数一直就只有1,当pb析构时,B的计数减一,变为0,B得到释放,
B释放的同时也会使A的计数减一,同时pa自己析构时也会使资源A的计数减一,那么A的计数为0,A得到释放。
*/
void main()
{
fun();
system("pause");
}
四、unique_ptr
unique_ptr 是一个独享所有权的智能指针,它提供了严格意义上的所有权。它取代了C++98中的auto_ptr。
用法和auto_ptr类似,详情见一下代码:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
unique_ptr<string> fun2(){
return unique_ptr<string>(new string("RUS"));
}
void fun(){
unique_ptr<string> pa(new string("CHN"));
//unique_ptr没有use_count()方法
unique_ptr<string> pb(new string("USA"));
pb = move(pa);
//p2=p1;//错误,不能直接用等于号
if (pa == nullptr)
cout << "pa现在为空" << endl;
cout << "*pb " << *pb << endl;//pb变成了“CHA”
string* ps = pb.release();//清空当前智能指针所指的资源对象,并返回指针
cout << "*ps " << *ps << endl;//ps变成了“CHA”
pa.reset(ps);//重置指向另一个对象
cout << "*pa " << *pa << endl;//pa变成了“CHA”
pb = fun2();//接收函数的返回值可以用等于号,因为使用了移动构造函数
cout << "*pb " << *pb << endl;//pb变成了“RUS”
}
void main()
{
fun();
system("pause");
}