C++每日一问:sizeof 和 strlen 的区别, class 和 struct 的异同, C 和 C++ struct 的区别

1、sizeof 和 strlen 的区别

1)sizeof(…)是 运算符,而不是一个函数。
在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组、指针、类型、对象、函数等。 它的功能是: 获得保证能容纳实现所建立的最大对象的字节大小。由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小。实际上,用sizeof来返回类型以及静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系

2) strlen(…)是函数,要在运行时才能计算。
参数必须是字符型指针(char*), 且必须是以’\0’结尾的。当数组名作为参数传入时,实际上数组就退化成指针了。

int ac[10];
    cout<<sizeof(ac)<<endl;
    cout<<strlen(ac)<<endl;     (ac相当于一个指针,但是strlen只能接受char*类型,所以编译时出错)

它的功能是:返回字符串的长度。该字符串可能是自己定义的,也可能是内存中随机的,该函数实际完成的功能是从代表该字符串的第一个地址开始遍历,直到遇到结束符’\0’。返回的长度大小不包括’\0’。

3)举例

char arr[10] = "Hello";
int len_one = strlen(arr);
int len_two = sizeof(arr); 
cout << len_one << " and " << len_two << endl;            
输出结果为:5 and 10
sizeof返回定义arr数组时,编译器为其分配的数组空间大小,不关心里面存了多少数据。
strlen只关心存储的数据内容,不关心空间的大小和类型。
char * parr = new char[10];
int len_one = strlen(parr);
int len_two = sizeof(parr);
int len_three = sizeof(*parr);
cout << len_one << " and " << len_two << " and " << len_three << endl;
输出结果:3 and 4 and 1
 第一个输出结果3实际上每次运行可能不一样,这取决于parr里面存了什么(从parr[0]开始直到遇到第一个'\0'结束);
 第二个结果实际上本意是想计算parr所指向的动态内存空间的大小,但是事与愿违,sizeof认为parr是个字符指针,
 因此返回的是该指针所占的空间(指针的存储用的是长整型,所以为4
 第三个结果,由于*parr所代表的是parr所指的地址空间存放的字符,所以长度为1。

2、 class 和 struct 的异同, C 和 C++ struct 的区别

之前只知道在C++中类和结构体的区别只有默认的防控属性(访问控制)不同,struct是public的,而class是private的。但经过上网查资料才发现,除了这个不同之外,还有很多的知识点需要掌握。下面就听我一一道来~

1、首先比较一下C中的结构体和C++中的结构体区别

C++中的struct是对C中的struct进行了扩充,所以增加了很多功能,主要的区别如下图所示:

在这里插入图片描述
上面罗列了在声明时的区别,在使用的过程中也有区别:

在C中使用结构体时需要加上struct,或者对结构体使用typedef取别名,而C++可直接使用,例如:

结构体声明,C和C++使用同一个
struct Student
{
    
    
	int  iAgeNum;
	string strName;
}
typedef struct Student Student2;//C中取别名

struct  Student  stu1;	//C中正常使用
Student2   stu2;		//C中通过取别名的使用
Student    stu3;		//C++使用

C与C++实际上编程思想的区别,C是面向过程,C++面向对象
所以在C中结构体就是不同类型数据的集合,并不涉及算法和操作。
而C++是把数据变量及对这些数据变量的相关算法和操作给封装起来。

2、C++中Struct与Class的区别

在C++中引入struct是为了保持对C程序的兼容,在引入之后C++对其进行了扩充,现在struct可以拥有静态成员、成员数据可进行初始化、拥有函数、也可以继承、甚至多态也支持。从表面看起来两者之间像是没有区别,有时你把程序中的所有class改为struct,程序也照常运行。之所以说是看起来呢,两者之间肯定还是有差别的啦。

2.1、内部成员变量及成员函数的默认防控属性

struct默认防控属性是public的,而class默认的防控属性是private的,例如:

struct A
{
    
    
	int iNum;
}
class B
{
    
    
	int iNum;
}

A a;
a.iNum = 2;		//没有问题,默认防控属性为public
B b;
b.iNum = 2;		//编译出错,默认防控属性为private

2.2、继承关系中默认防控属性的区别

在继承关系,struct默认是public的,而class是private,例如:

struct A
{
    
    
	int   iAnum;
}
struct B : A
{
    
    
	int   iBnum;
}


A a;
a.iAnum = 1;	//在struct情况下是正确的,在class情况下是错误的

在是struct的情况下B是默认public继承A的。如果将上面的struct改成class,那么B是private继承A的。

上面的列子都是struct继承struct,class继承class,那么class与struct继承会怎样呢?
结论是:默认的防控属性取决于子类而不是基类,例如:

struct A{
    
    };
class B : A {
    
    };	//默认为private继承
struct C : B{
    
    };	//默认为public继承

所以我们在写代码的时候,为了不引起歧义,最好指明继承的方式,而不要用默认的继承,例如:

class B : public A{
    
    }struct B : public A{
    
    }

2.3、模板中的使用

class这个关键字还可用于定义模板参数,就像typename。但是strcut不用与定义模板参数,例如:

template< typename T, typename Y >	//可以把typename 换成 class
int  Func( const T& t, const Y& y )
{
    
    
	//TODO
}

2.4、{}赋初值的讨论

因为C++是对C的扩充,那么它就兼容过去C中struct的特性,例如:

struct A
{
    
    
	char 	c1;
	int		i2;
	double	db3;
};

A a = {
    
    'p', 7, 451.154}; //定义时赋初值,在struct时没问题,在class时出错

当然这里在class时,默认的防控属性为private,所以出错正常,但这是它们之间的一个区别吗?不是的。
在struct中加入一个构造函数(或虚函数),你会发现struct也不能用{}赋值了。嗯?头顶上有个大大的问号。

原因是以{}的方式来赋初值,只是用一个初始化列表来对数据进行按顺序的初始化,如果上面写成A a = {‘p’,7};则c1,i2被初始化,而db3没有。这样简单的copy操作,只能发生在简单的数据结构上,而不应该放在对象上。加入一个构造函数或是一个虚函数会使strcut更体现出一种对象的特性,而是{}操作不在有效

因为加入这样的函数(构造和虚函数),使得类的内部结构发生了变化。而加入一个普通的成员函数呢?你会发现{}依旧可用。其实你可以将普通的函数理解成对数据结构的一种算法,这并不打破它数据结构的特性。

2.5总结

通过上面的总结,你会发现两者的差别确实没有很大。尤其是在我们书写程序的过程中显示指明防控属性时,那我们什么时候用class,什么时候用struct呢?

个人建议:当你觉得你要做的更像是一种数据结构集合的话,那么用struct。如果你要做的更像是一种对象的话,那么用class

猜你喜欢

转载自blog.csdn.net/m0_37251750/article/details/121094726