美文网首页C语言学习
容易犯错的c++小细节

容易犯错的c++小细节

作者: 榆西带你飞 | 来源:发表于2017-04-27 13:38 被阅读57次

这篇文章主要总结一下,自己见到的一些易犯错的小问题!供自己和大家参考和借鉴!

(1)运行下图中的C++代码,输出是什么?

intSizeOf(charpString[])

{

returnsizeof(pString);

}

intmain(intargc, char* argv[])

{

char* pString1 ="google";

intsize1 =sizeof(pString1);

intsize2 =sizeof(*pString1);

charpString2[100] ="google";

intsize3 =sizeof(pString2);

intsize4 = SizeOf(pString2);

printf("%d, %d, %d, %d \n", size1, size2, size3, size4);

return0;

}

答案:4, 1, 100, 4。pString1是一个指针。在32位机器上,任意指针都占4个字节的空间。*pString1是字符串pString1的第一个字符。一个字符占一个字节。pString2是一个数组,sizeof(pString2)是求数组的大小。这个数组包含100个字符,因此大小是100个字节。而在函数SizeOf中,虽然传入的参数是一个字符数组,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。

我建立了一个C语言学习交流群,在群里有很多新手教程和大神交流q群,怎么找到先搜索178在加上923最后还有056,这样你就可以找到组织一起学习,群里人很多都是新手在大神的帮助下,已经成长为高薪工程师,你不来对我们没有任何损失,但是只要你来了基本可以有很多的收获。

(2)

#include

using namespace std;

classA

{

public:

A()

{std::cout <<"A is created."<< std::endl;}

~A()

{std::cout <<"A is deleted."<< std::endl;}

};

classB :publicA

{

public:

B()

{std::cout <<"B is created."<< std::endl;}

~B()

{std::cout <<"B is deleted."<< std::endl;}

};

intmain(intargc, char* argv[])

{

A* pA =newB();

deletepA;

return0;

}

答案:输出三行,分别是:A is created. B is created. A is deleted。用new创建B时,回调用B的构造函数。在调用B的构造函数的时候,会先调用A的构造函数。因此先输出A is created. B is created.

接下来运行delete语句时,会调用析构函数。由于pA被声明成类型A的指针,同时基类A的析构函数没有标上virtual,因此只有A的析构函数被调用到,而不会调用B的析构函数。

由于pA实际上是指向一个B的实例的指针,但在析构的时候只调用了基类A的析构函数,却没有调用B的析构函数。这就是一个问题。如果在类型B中创建了一些资源,比如文件句柄、内存等,在这种情况下都得不到释放,从而导致资源泄漏。

(3)

#include

#include

using namespace std;

struct Point3D

{

int x;

int y;

int z;

};

int main(int argc, char* argv[])

{

Point3D* pPoint = NULL;

int offset = (int)(&(pPoint->z));

printf("%d\n", offset);

return 0;

}

输出8。由于在pPoint->z的前面加上了取地址符号,运行到此时的时候,会在pPoint的指针地址上加z在类型Point3D中的偏移量8。由于pPoint的地址是0,因此最终offset的值是8。

&(pPoint->z)的语意是求pPoint中变量z的地址(pPoint的地址0加z的偏移量8),并不需要访问pPoint指向的内存。只要不访问非法的内存,程序就不会出错。

我建立了一个C语言学习交流群,在群里有很多新手教程和大神交流q群,怎么找到先搜索178在加上923最后还有056,这样你就可以找到组织一起学习,群里人很多都是新手在大神的帮助下,已经成长为高薪工程师,你不来对我们没有任何损失,但是只要你来了基本可以有很多的收获。

(4)

classA

{

private:

intm_value;

public:

A(intvalue)

{

m_value = value;

}

voidPrint1()

{

printf("hello world");

}

voidPrint2()

{

printf("%d", m_value);

}

};

intmain(intargc, char* argv[])

{

A* pA = NULL;

pA->Print1();

pA->Print2();

return0;

}

分析:答案是Print1调用正常,打印出hello world,但运行至Print2时,程序崩溃。调用Print1时,并不需要pA的地址,因为Print1的函数地址是固定的。编译器会给Print1传入一个this指针,该指针为NULL,但在Print1中该this指针并没有用到。只要程序运行时没有访问不该访问的内存就不会出错,因此运行正常。在运行print2时,需要this指针才能得到m_value的值。由于此时this指针为NULL,因此程序崩溃了。

(5)

C++中我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函数(写在函数的最后表示不能修改成员变量,不是指写在前面表示返回值为常量)。请问:能不能同时用static和const修饰类的成员函数?

分析:答案是不可以。C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时static的用法和static是冲突的。

(6)

C++中静态成员函数能不能同时也是虚函数?

分析:答案是不能。调用静态成员函数不要实例。但调用虚函数需要从一个实例中指向虚函数表的指针以得到函数的地址,因此调用虚函数需要一个实例。两者相互矛盾。


我建立了一个C语言学习交流群,在群里有很多新手教程和大神交流q群,怎么找到先搜索178在加上923最后还有056,这样你就可以找到组织一起学习,群里人很多都是新手在大神的帮助下,已经成长为高薪工程师,你不来对我们没有任何损失,但是只要你来了基本可以有很多的收获。

相关文章

  • 容易犯错的c++小细节

    这篇文章主要总结一下,自己见到的一些易犯错的小问题!供自己和大家参考和借鉴! (1)运行下图中的C++代码,输出是...

  • 产品经理特别容易犯错的小细节

    包括但不限于以下的这些清单。 1. 容易追求完美 一个版本里想要的太多。希望一个版本更新之后收入上去了,活跃度上去...

  • 清单革命(2018.11.18)

    一、细节上犯错容易成不靠谱的人 小明平时工作努力,加班加点,经常干活到深夜,结果总在非常小的细节上出现纰漏,导致你...

  • 有哪些是你进了体制内才知道的事情?

    不算完全在体制内,但基本天天跟里面各种各样的人打交道。稍微说一些比较容易被忽视或者容易犯错的小细节和经验。供大家参...

  • 人性的弱点------别忽略爱里的小细节

    生活中有很多很容易做到,也容易被忽略的小细节。 但往往就是这些小细节,可以让我们在偶尔会有些苦涩的生活...

  • 细节

    都说细节决定成败,为什么呢? 细节往往因其“小”,而容易被人忽视,掉以轻心; 因其“细...

  • Java与C++关于构造函数的差异

    case1 Java: C++: C++输出为: Java输出为: 这个例子体现了C++在Java的细节差异: J...

  • Android 容易遗漏的刷新小细节

    前言 系列文章:Android Activity创建到View的显示过程[https://www.jianshu....

  • 犯错很容易,犯错之后呢?

    前天看了一本书叫正面管教,里面讲到了一个概念是:犯错是学习的大好时机,深有感触,不仅对于孩子来说犯错是学习的大好时...

  • 插画临摹过程分析-5

    原画: 临摹大场景的时候发现自己对细节对把控很差,最近需要练习小元素 小元素更容易看见细节,光影关系 一个小插画对...

网友评论

    本文标题:容易犯错的c++小细节

    本文链接:https://www.haomeiwen.com/subject/lsggzttx.html