【300分】讨论,为什么非静态成员函数不是左值?

飞天御剑流 2011-09-05 07:00:57
还是左值问题。

预备知识:

C++的左值包括函数,但不包括成员函数,即成员函数不是左值,也由于这个原因,成员函数不存在象普通函数那样的函数到指针的左值转换,例如:


struct A
{
static void foo1( ){}
void foo2( ){}
};
.......
void ( *p1 )() = A::foo1; //合法,因为静态函数的类型种类属于普通函数,存在函数到指针的左值转换
void ( A::*p2 )( ) = A::foo2; //非法,成员函数不存在左值转换
void ( A::*p3 )() = &A::foo2; //合法,需要显式取地址运算


问题是,为什么非静态成员函数不是左值?
...全文
1955 139 打赏 收藏 转发到动态 举报
写回复
用AI写文章
139 条回复
切换为时间正序
请发表友善的回复…
发表回复
lovemyselfwys 2011-09-20
  • 打赏
  • 举报
回复
围观,表示看不懂
FengPrince 2011-09-20
  • 打赏
  • 举报
回复
[Quote=引用 123 楼 frankhb1989 的回复:]
引用 110 楼 fengprince 的回复:

引用 27 楼 supermegaboy 的回复:

楼上各位朋友所列出的条款,特别是2楼和8楼,仅说明非静态成员函数是一个右值或者非静态成员函数不存在隐式转换,这个事实我已经在提出的问题中阐述了。

但是,如果问一句:为什么要这么做?不是更有趣么?

非静态成员函数也是函数,为什么函数左值单单不包含它?难道非静态成员函数有什么特……
[/Quote]
嗯,字打快了,笔误。。。
话说,我上了两个星期的课,回来一看,LZ还没结贴,该不会忘了吧!!!
七擒关羽 2011-09-20
  • 打赏
  • 举报
回复
mark~
pamtry 2011-09-11
  • 打赏
  • 举报
回复
感觉最近一个月离C\C++有点远,mark一下回头看看
qwer_boo 2011-09-11
  • 打赏
  • 举报
回复
英语还是得好好学才是啊...
mainsea 2011-09-11
  • 打赏
  • 举报
回复
随便来瞅瞅
冼鸿文 2011-09-09
  • 打赏
  • 举报
回复
因为他就是右值
冼鸿文 2011-09-08
  • 打赏
  • 举报
回复
楼主的问题都是左值的问题
rangf 2011-09-08
  • 打赏
  • 举报
回复
[Quote=引用 126 楼 supermegaboy 的回复:]

我决定向一位大人物发一封信,如果有结果,会告诉大家。
[/Quote]

期待~~~!
ColdMooon 2011-09-08
  • 打赏
  • 举报
回复
Bjarne Stroustrup么?
飞天御剑流 2011-09-08
  • 打赏
  • 举报
回复
[Quote=引用 124 楼 frankhb1989 的回复:]
引用 114 楼 supermegaboy 的回复:

其实所有东西都归结在标准一个脚注上:

50)This conversion never applies to nonstatic member functions because an lvalue that refers to a nonstatic member function cannot be obtained.


……
[/Quote]

没错。如果允许非静态成员函数到指针的转换,那么结果当然应该就是成员函数指针类型了。只是奇怪的是,隐式转换被禁止的同时却允许另一个导致相同结果的&操作,这是最让人想不通的地方。

我决定向一位大人物发一封信,如果有结果,会告诉大家。
Zeroins 2011-09-08
  • 打赏
  • 举报
回复
我试了一下

void ( A::*p3 )() = &A::foo2;

A a;
(a.*p3)();

的情况,ida后发现编译器是可以解决_thiscall下通过寄存器的隐式this指针传递的问题的
也即在实现层面上是不存在困难的

那么我的推测就是错误的

这个问题很可能和实现无关了,还是从语言本身找原因吧

FrankHB1989 2011-09-08
  • 打赏
  • 举报
回复
[Quote=引用 114 楼 supermegaboy 的回复:]

其实所有东西都归结在标准一个脚注上:

50)This conversion never applies to nonstatic member functions because an lvalue that refers to a nonstatic member function cannot be obtained.


只要搞清楚“an lvalue that refers ……
[/Quote]
以下是新的猜想。
换一个角度想。
如果can be obtained,那么能有什么操作呢。作为lvalue的意义有多少?
不过已经有非成员函数/静态成员函数的先例了。不妨说,问题在于为什么非成员函数/静态成员函数是左值,而非静态成员函数在这点上刻意有区别?类型上是没什么区别的……
作为lvalue存在的函数是照顾早已存在的function-to-pointer conversion吗(如果不是lvalue就没法在一些上下文中区分了)?
如果承认这点,那么,问题又变为,非静态成员函数为什么不适用function-to-pointer conversion?
再次把棋盘翻转过来考虑。
如果成员函数是lvalue,且允许对成员函数进行function-to-pointer conversion,那么如何确定结果的类型?注意指针类型和成员指针类型是不同的类型(这可能是受到实现限制的条件下为了保持类型安全性);而这时函数引用按照其它规则也可以引用到成员函数上了。难道还要再定义“成员引用”类型吗(那么,这里的“引用”类型的语义是什么)?
无论对实现还是对标准本身来说,在这里做文章的代价大了点。如果当时的主流实现是这样那么另当别论,可惜不是。

FrankHB1989 2011-09-08
  • 打赏
  • 举报
回复
[Quote=引用 110 楼 fengprince 的回复:]

引用 27 楼 supermegaboy 的回复:

楼上各位朋友所列出的条款,特别是2楼和8楼,仅说明非静态成员函数是一个右值或者非静态成员函数不存在隐式转换,这个事实我已经在提出的问题中阐述了。

但是,如果问一句:为什么要这么做?不是更有趣么?

非静态成员函数也是函数,为什么函数左值单单不包含它?难道非静态成员函数有什么特别的东西阻止它成为大家的一员?老实说,我也还没有答案。……
[/Quote]
这里提到的关于引用类型的观点和我之前的猜想相同。
不过“但non-static成员函数是不存在引用类型的。所以,non-static成员函数不可能为值。还有一点是若真为左值的话,必然存在引用类型,这样通过对象调用时会与类的数据成员形式产生歧义!!”——这里笔误了吧。
另外,register关键字在C++0x里deprecated掉了,不过离废除还差一步。

Zeroins 2011-09-08
  • 打赏
  • 举报
回复
也就是说楼主认为此问题与实现无关
纯粹是出于语义自洽或其他语言层面上的考虑来规定的

不知会不会有高手从语言中翻出一个比较可能的解释,坐等吧~~~~~~

另:
“反过来不行,不能也无法从实现中去推测抽象语义”
我并不是要反推,只是在从语义上找不到一条规定可能的解释时,试着从实现的角度来考虑问题
楼主也说“c/c++标准就是以实现为基础的”
“抽象与实现并不是一一对应的,从实现去推测抽象很容易会得出错误的结论。”
这点我很赞同,但抛掉实现有时又无法摸到问题的本质,同样忽视实现,很多推测也会得出错误的结论
不过不论如何,我们都并不能百分百肯定自己的理解就是语言标准制定时真正所考量和依据的

思维方式不同可能与个人经历不同有关,我是做较低层的
实际工作中很多微妙的问题都是需要下到底层才能理解和解决的
飞天御剑流 2011-09-08
  • 打赏
  • 举报
回复
c/c++标准就是以实现为基础的,但是,反过来不行,不能也无法从实现中去推测抽象语义,因为,抽象与实现并不是一一对应的,从实现去推测抽象很容易会得出错误的结论。
Zeroins 2011-09-08
  • 打赏
  • 举报
回复
[Quote=引用 117 楼 stendson 的回复:]
个人认为:a=b是取出右值b存储的值赋给左值a的地址,所以左值也可以是右值
因为静态成员已经在对象建立(运行时)之前就分配了内存,所以引用已经分配的内存地址是合法的,但是引用非静态成员,即对象还没建立也就没有为成员函数分配内存,就无法索引,可以通过对象取地址即
A a;
void ( A::*p2 )( ) = a.foo2;
但是函数已经定义了就存在结构体的public的内存区域(对象……
[/Quote]

这种解释适合成员变量,不适合成员函数

即使没有定义相应的类对象,如果非静态成员函数中未使用类的其他成员函数和变量,也是可用通过嵌入汇编,手动模拟一个_thiscall调用方式来调用非静态成员函数的,因为非静态成员函数指令块的存在与否并不依赖于具体对象。自己反汇编一看就很清楚了
tulipcaicai 2011-09-08
  • 打赏
  • 举报
回复
学习一下
Zeroins 2011-09-08
  • 打赏
  • 举报
回复
"左值的涵义与指针的实现并无关联。"

是的

我只是从之前个人对c++对象实现的分析经验来考虑的
因为《深度探索C++对象模型》中所描述的很多c++中的规定和特性都是有其深层次的基于实现的考虑的,而非仅仅从语言本身考虑
也就是说很多规定是基于编译器实现的实践经验来制定的

也许本条不属于?
stendson 2011-09-08
  • 打赏
  • 举报
回复
个人认为:a=b是取出右值b存储的值赋给左值a的地址,所以左值也可以是右值
因为静态成员已经在对象建立(运行时)之前就分配了内存,所以引用已经分配的内存地址是合法的,但是引用非静态成员,即对象还没建立也就没有为成员函数分配内存,就无法索引,可以通过对象取地址即
A a;
void ( A::*p2 )( ) = a.foo2;
但是函数已经定义了就存在结构体的public的内存区域(对象的函数公共部分)里,手动取地址也是合法的。
加载更多回复(117)
doc格式,60多页吧,几百道题吧,都有答案吧,看好在下!部:1.求下面函数的返回值(微软)int func(x) { int countx = 0; while(x) { countx ++; x = x&(x-1); } return countx; } 假定x = 9999。 答案:8思路:将x转化为2进制,看含有的1的个数。2. 什么是“引用”?申明和使用“引用”要注意哪些问题?答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进行初始化。引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用配存储单元。不能建立数组的引用。3. 将“引用”作为函数参数有哪些特点?(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。4. 在什么时候需要使用“常引用”? 如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名;例1int a ;const int &ra=a;ra=1; //错误a=1; //正确 例2string foo( );void bar(string & s); 那么下面的表达式将是法的:bar(foo( ));bar("hello world"); 原因在于foo( )和"hello world"串都会产生一个临时对象,而在C++中,这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为const类型,这是法的。引用型参数应该在能被定义为const的情况下,尽量定义为const 。5. 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!注意事项:(1)不能返回局部变量的引用。这条可以参照Effective C++[1]的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。 (2)不能返回函数内部new配的内存的引用。这条可以参照Effective C++[1]的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new配)就无法释放,造成memory leak。(3)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。(4)流操作符重载返回值申明为“引用”的作用:流操作符<>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。例3#i nclude int &put(int n);int vals[10];int error=-1;void main(){put(0)=10; //以put(0)函数值作为左值,等价于vals[0]=10; put(9)=20; //以put(9)函数值作为左值,等价于vals[9]=20; cout<=0 && n<=9 ) return vals[n]; else { cout<<"subscript error"; return error; }} (5)在另外的一些操作符中,却千万不能返回引用:+-*/ 四则运算符。它们不能返回引用,Effective C++[1]的Item23详细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new配的对象的引用、返回一个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。所以可选的只剩下返回一个对象了。6. “引用”与多态的关系?引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。例4Class A; Class B : Class A{...}; B b; A& ref = b;7. “引用”与指针的区别是什么?指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。此外,就是上面提到的对函数传ref和pointer的区别。8. 什么时候需要“引用”?流操作符<>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。以上 2-8 参考:http://blog.csdn.net/wfwd/archive/2006/05/30/763551.aspx9. 结构与联合有和区别?1. 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。 2. 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。10. 下面关于“联合”的题目的输出?a)#i nclude union{int i;char x[2];}a;void main(){a.x[0] = 10; a.x[1] = 1;printf("%d",a.i);}答案:266 (低位低地址,高位高地址,内存占用情况是Ox010A)………………
《深入理解C++11:C++11新特性解析与应用》主要内容:国内首本全面深入解读C++11新标准的专著,由C++标准委员会代表和IBM XL编译器中国开发团队共同撰写。不仅详细阐述了C++11标准的设计原则,而且系统地讲解了C++11新标准中的所有新语言特性、新标准库特性、对原有特性的改进,以及如何应用所有这些新特性。 全书一共8章:第1章从设计思维和应用范畴两个维度对C++11新标准中的所有特性进行了类,呈现了C++11新特性的原貌;第2章讲解了在保证与C语言和旧版C++标准充兼容的原则下增加的一些新特性;第3章讲解了具有广泛可用性、能与其他已有的或者新增的特性结合起来使用的、具有普适性的一些新特性;第4章讲解了C++11新标准对原有一些语言特性的改进,这些特性不仅能让C++变得更强大,还能提升程序员编写代码的效率;第5章讲解了C++11在安全方面所做的改进,主要涵盖枚举类型安全和指针安全两个方面的内容;第6章讲解了为了进一步提升和挖掘C++程序性能和让C++能更好地适应各种新硬件的发展而设计的新特性,如多核、多线程、并行编程方面的新特性;第7章讲解了一些颠覆C++一贯设计思想的新特性,如lambda表达式等;第8章讲解了C++11为了解决C++编程中各种典型实际问题而做出的有效改进,如对Unicode的深入支持等。附录中则介绍了C++11标准与其他相关标准的兼容性和区别、C++11中弃用的特性、编译器对C++11的支持情况,以及学习C++11的相关资源。 《深入理解C++11:C++11新特性解析与应用》 免责声明 序 前言 第1章 新标准的诞生 1 1.1 曙光:C++11标准的诞生 1 1.1.1 C++11/C++0x(以及C11/C1x)—新标准诞生 1 1.1.2 什么是C++11/C++0x 2 1.1.3 新C++语言的设计目标 3 1.2 今时今日的C++ 5 1.2.1 C++的江湖地位 5 1.2.2 C++11语言变化的领域 5 1.3 C++11特性的类 7 1.4 C++特性一览 11 1.4.1 稳定性与兼容性之间的抉择 11 1.4.2 更倾向于使用库而不是扩展语言来实现特性 12 1.4.3 更倾向于通用的而不是特殊的手段来实现特性 13 1.4.4 专家新手一概支持 13 1.4.5 增强类型的安全性 14 1.4.6 与硬件紧密合作 14 1.4.7 开发能够改变人们思维方式的特性 15 1.4.8 融入编程现实 16 1.5 本书的约定 17 1.5.1 关于一些术语的翻译 17 1.5.2 关于代码中的注释 17 1.5.3 关于本书中的代码示例与实验平台 18 第2章 保证稳定性和兼容性 19 2.1 保持与C99兼容 19 2.1.1 预定义宏 19 2.1.2 __func__预定义标识符 20 2.1.3 _Pragma操作符 22 2.1.4 变长参数的宏定义以及__VA_ARGS__ 22 2.1.5 宽窄字符串的连接 23 2.2 long long整型 23 2.3 扩展的整型 25 2.4 宏__cplusplus 26 2.5 静态断言 27 2.5.1 断言:运行时与预处理时 27 2.5.2 静态断言与static_assert 28 2.6 noexcept修饰符与noexcept操作符 32 2.7 快速初始化成员变量 36 2.8 静态成员的sizeof 39 2.9 扩展的friend语法 40 2.10 final/override控制 44 2.11 模板函数的默认模板参数 48 2.12 外部模板 50 2.12.1 为什么需要外部模板 50 2.12.2 显式的实例化与外部模板的声明 52 2.13 局部和匿名类型作模板实参 54 2.14 本章小结 55 第3章 通用为本,专用为末 57 3.1 继承构造函数 57 3.2 委派构造函数 62 3.3 右值引用:移动语义和完美转发 68 3.3.1 指针成员与拷贝构造 68 3.3.2 移动语义 69 3.3.3 左值、右值与右值引用 75 3.3.4 std::move:强制转化为右值 80 3.3.5 移动语义的一些其他问题 82 3.3.6 完美转发 85 3.4 显式转换操作符 89 3.5 列表初始化 92 3.5.1 初始化列表 92 3.5.2 防止类型收窄 96 3.6 POD类型 98 3.7 受限联合体 106 3.8 用户自定义字面量 110 3.9 内联名字空间 113 3.10 模板的别名 118 3.11 一般化的SFINEA规则 119 3.12 本章小结 121 第4章 新手易学,老兵易用 123 4.1 右尖括号>的改进 123 4.2 auto类型推导 124 4.2.1 静态类型、动态类型与类型推导 124 4.2.2 auto的优势 126 4.2.3 auto的使用细则 130 4.3 decltype 134 4.3.1 typeid与decltype 134 4.3.2 decltype的应用 136 4.3.3 decltype推导四规则 140 4.3.4 cv限制符的继承与冗余的符号 143 4.4 追踪返回类型 145 4.4.1 追踪返回类型的引入 145 4.4.2 使用追踪返回类型的函数 146 4.5 基于范围的for循环 150 4.6 本章小结 153 第5章 提高类型安全 155 5.1 强类型枚举 155 5.1.1 枚举:门别类与数值的名字 155 5.1.2 有缺陷的枚举类型 156 5.1.3 强类型枚举以及C++11对原有枚举类型的扩展 160 5.2 堆内存管理:智能指针与垃圾回收 163 5.2.1 显式内存管理 163 5.2.2 C++11的智能指针 164 5.2.3 垃圾回收的类 167 5.2.4 C++与垃圾回收 169 5.2.5 C++11与最小垃圾回收支持 170 5.2.6 垃圾回收的兼容性 172 5.3 本章小结 173 第6章 提高性能及操作硬件的能力 174 6.1 常量表达式 174 6.1.1 运行时常量性与编译时常量性 174 6.1.2 常量表达式函数 176 6.1.3 常量表达式值 178 6.1.4 常量表达式的其他应用 180 6.2 变长模板 183 6.2.1 变长函数和变长的模板参数 183 6.2.2 变长模板:模板参数包和函数参数包 185 6.2.3 变长模板:进阶 189 6.3 原子类型与原子操作 196 6.3.1 并行编程、多线程与C++11 196 6.3.2 原子操作与C++11原子类型 197 6.3.3 内存模型,顺序一致性与memory_order 203 6.4 线程局部存储 214 6.5 快速退出:quick_exit与at_quick_exit 216 6.6 本章小结 219 第7章 为改变思考方式而改变 220 7.1 指针空值—nullptr 220 7.1.1 指针空值:从0到NULL,再到nullptr 220 7.1.2 nullptr和nullptr_t 223 7.1.3 一些关于nullptr规则的讨论 225 7.2 默认函数的控制 227 7.2.1 类与默认函数 227 7.2.2 “= default”与“= deleted” 230 7.3 lambda函数 234 7.3.1 lambda的一些历史 234 7.3.2 C++11中的lambda函数 235 7.3.3 lambda与仿函数 238 7.3.4 lambda的基础使用 240 7.3.5 关于lambda的一些问题及有趣的实验 243 7.3.6 lambda与STL 247 7.3.7 更多的一些关于lambda的讨论 254 7.4 本章小结 256 第8章 融入实际应用 258 8.1 对齐支持 258 8.1.1 数据对齐 258 8.1.2 C++11的alignof和alignas 261 8.2 通用属性 267 8.2.1 语言扩展到通用属性 267 8.2.2 C++11的通用属性 268 8.2.3 预定义的通用属性 270 8.3 Unicode支持 274 8.3.1 字符集、编码和Unicode 274 8.3.2 C++11中的Unicode支持 276 8.3.3 关于Unicode的库支持 280 8.4 原生字符串字面量 284 8.5 本章小结 286 附录A C++11对其他标准的不兼容项目 287 附录B 弃用的特性 294 附录C 编译器支持 301
学习并掌握C++2.0(11+14+17+20)的新特性,学习线程及线程池的应用 ---------------------------------------------------给小白学员的3年学习路径及计划技术方面三块:1.纯开发技术方向2.音视频流媒体专业方向3.项目实战---------------------------------------------------1.纯开发技术方向(1) C++必须要过硬(至少学会10本经典好书)(2) 系统级编程(Windows、Linux),必须特别熟练系统API,灵活运用(3) 框架与工具(Qt、MFC):必须精通其中一种。(4) 架构与设计模式:需要提升一个高度,不再是简单的编码,而是思维模式。(5) 驱动级别(如果有兴趣,可以深入到驱动级:包括Windows、Linux)(6) 最好学习点Java+Html+javascript等WEB技术。2.音视频流媒体专业方向(1) 音视频流媒体基础理论:   必须认真学会,否则看代码就是看天书(2) 编解码方向:精通h.264,h.265(hevc), 包括理论和各个开源库(ffmpeg,libx264,libx265,...)。(3) 直播方向:  精通各种直播协议(rtsp,rtmp,hls,http-flv,...), 钻研各个开源库(live555,darwin,srs,zlmediakit,crtmpserver,...)(4) 视频监控:  理论+开源库(onvif+281818)(EasyMonitor、iSpy、ZoneMinder(web)、...) 3.项目实战(1) Qt项目:  至少要亲手练习10个实战项目(网络服务器、多线程、数据库、图像处理、多人聊天、等等)(2)音视频项目:包括编解码、视频监控、直播等各个方向,都需要亲手实战项目,包括视频服务器、后台管理系统、前端播放器(多端)---------------------------------------------------  第1章 C++11新特性 41). nullptr关键字与新语法 42). auto和decltype类型推导 6 auto讲解 6 auto示例 7 decltype 83). for区间迭代 94). 初始化列表 105). 模板增强 11外部模板 11类型别名模板 12默认模板参数 126). 构造函数 13委托构造 13继承构造 147). Lambda 表达式 158). 新增容器 20std::array 20std::forward_list 21无序容器 22元组 std::tuple 239). 正则表达式 2610). 语言级线程支持 28多线程库简介 2811). 右值引用和move语义 31右值引用和move语义 32转移左值 3412). constexpr 35第2章 C++14新特性 36Lambda 函数 36类型推导 37返回值类型推导(Return type deduction) 37泛型lambda 39[[弃用的]]  [[deprecated]]属性 40二进制数字和数字隔符 41第3章 C++17新特性 42安装GCC10.2 42安装msys2-x86_64-20200720 42更新镜像 42更新软件库 43安装 MinGW64 等必要的软件 43环境变量Path 43编译命令 43constexpr 44typename 45折叠表达式 47结构化绑定 48条件支语句初始化 49聚合初始化 50嵌套命名空间 52lambda表达式捕获*this的值 53改写/继承构造函数 54用auto作为类型模板参数 55__has_include 56fallthrough 57nodiscard 57maybe_unused 58第4章 C++20新特性 59编译命令 59concept 59typename 60explicit 61constinit 62位域变量的默认成员初始化 62指定初始化 63基于范围的for循环初始化 64放宽基于范围的for循环,新增自定义范围方法 65嵌套内联命名空间 66允许用圆括弧的值进行聚合初始化 67unicode字符串字面量 68允许转换成未知边界的数组 68likely和unlikely 69第5章 C++2.0(11/14/17/20)总结与析 705.1 C语言与C++ 715.2 语言可用性的强化 725.2.1 常量 725.2.2 变量及其初始化 735.2.3 类型推导 745.2.4 控制流 765.2.5 模板 775.2.6 面向对象 815.3 语言运行期的强化 835.3.1 Lambda 表达式 835.3.2 右值引用 865.4 容器 885.4.1 线性容器 885.4.2 无序容器 895.4.3 元组 895.5 智能指针与内存管理 905.5.1 RAII 与引用计数 905.5.2 std::shared_ptr 905.5.3 std::unique_ptr 915.5.4 std::weak_ptr 91第6章 C++2.0多线程原理与实战 93什么是并发 93并发的方式 93为什么使用并发 95线程简介 96创建线程的三种方式 971. 通过函数 972.通过类对象创建线程 993.通过lambda表达式创建线程 101thread线程的使用 101互斥量与临界区 105期物Future 111条件变量 112原子操作 114内存模型 118第7章 C++2.0线程池原理与实战 120线程与线程池的基本原理 1201)、线程 1202)、线程的生命周期 1213)、什么是单线程和多线程 1214)、线程池 1225)、四种常见的线程池 123线程池的架构与流程 123线程池代码实战 125    
强烈建议大家看一看这本书,pdf格式的,不是影印的,含有目录,看起来特别方便,写的很详细,诙谐幽默. 最冤枉的关键字----sizeof...............................................................................................18 1.5.1,常年被人误认为函数...........................................................................................18 1.5.2,sizeof(int)*p 表示什么意思?........................................................................18 1.4,signed、unsigned 关键字................................................................................................19 1.6,if、else 组合.................................................................................................................... 20 1.6.1,bool 变量与“零值”进行比较...............................................................................20 1.6.2, float 变量与“零值”进行比较.................................................................................21 1.6.3,指针变量与“零值”进行比较...............................................................................21 1.6.4,else 到底与哪个if 配对呢?...............................................................................22 1.6.5,if 语句后面的号............................................................................................... 23 1.6.6,使用if 语句的其他注意事项.............................................................................. 24 1.7,switch、case 组合........................................................................................................... 24 1.7.1,不要拿青龙偃月刀去削苹果.............................................................................. 24 1.7.2,case 关键字后面的值有什么要求吗?.............................................................. 25 1.7.3,case 语句的排列顺序...........................................................................................25 1.7.4,使用case 语句的其他注意事项..........................................................................27 1.8,do、while、for 关键字................................................................................................... 28 1.8.1,break 与continue 的区别.....................................................................................28 1.8.2,循环语句的注意点...............................................................................................29 1.9,goto 关键字......................................................................................................................30 1.10,void 关键字....................................................................................................................31 1.10.1,void a?............................................................................................................31 1.10,return 关键字................................................................................................................. 34 1.11,const 关键字也许该被替换为readolny....................................................................... 34 1.11.2,节省空间,避免不必要的内存配,同时提高效率.................................... 35 1.12,最易变的关键字----volatile.......................................................................................... 36 1.13,最会带帽子的关键字----extern.................................................................................... 37 1.14,struct 关键字..................................................................................................................38 1.14.1,空结构体多大?.................................................................................................38 1.14.2,柔性数组.............................................................................................................39 1.14.3,struct 与class 的区别.........................................................................................40 1.15,union 关键字..................................................................................................................40 1.15.1,大小端模式对union 类型数据的影响............................................................. 40 1.15.2,如何用程序确认当前系统的存储模式?........................................................ 41 1.16,enum 关键字..................................................................................................................42 1.16.1, 枚举类型的使用方法..........................................................................................43 1.16.2,枚举与#define 宏的区别....................................................................................43 1.17,伟大的缝纫师----typedef 关键字................................................................................. 44 1.17.1,关于马甲的笑话.................................................................................................44 1.17.2,历史的误会----也许应该是typerename........................................................... 44 1.17.3,typedef 与#define 的区别...................................................................................45 1.17.4,#define a int[10]与typedef int a[10];.............................................................. 46 第二章符号....................................................................................................................................49 2.1,注释符号..........................................................................................................................50 2.1.1,几个似而是的注释问题...................................................................................50 2.1.2,y = x/*p................................................................................................................. 51 2.1.3,怎样才能写出出色的注释...................................................................................51 2.1.3.1,安息吧,路德维希.凡.贝多芬................................................................. 51 2.1.3.2,windows 大师们用注释讨论天气问题....................................................51 2.1.3.3,出色注释的基本要求............................................................................... 52 2.2,接续符和转义符..............................................................................................................53 2.3,单引号、双引号..............................................................................................................54 2.4,逻辑运算符......................................................................................................................54 2.5,位运算符..........................................................................................................................55 2.5.1,左移和右移...........................................................................................................55 2.5.2,0x01<<2+3 的值为多少?...................................................................................55 2.6,花括号..............................................................................................................................56 2.7,++、--操作符...................................................................................................................56 2.7.1,++i+++i+++i......................................................................................................... 57 2.7.2,贪心法...................................................................................................................57 2.8,2/(-2)的值是多少?.........................................................................................................58 2.9,运算符的优先级..............................................................................................................58 2.9.1, 运算符的优先级表................................................................................................58 2.9.2,一些容易出错的优先级问题.............................................................................. 60 第三章预处理................................................................................................................................61 3.1,宏定义..............................................................................................................................62 3.1.1,数值宏常量...........................................................................................................62 3.1.2,字符串宏常量.......................................................................................................62 3.1.3,用define 宏定义注释符号?.............................................................................. 63 3.1.4,用define 宏定义表达式.......................................................................................63 3.1.5,宏定义中的空格...................................................................................................64 3.1.6,#undef....................................................................................................................64 3.2,条件编译..........................................................................................................................65 3.3,文件包含..........................................................................................................................66 3.4,#error 预处理................................................................................................................... 66 3.5,#line 预处理.....................................................................................................................67 3.6,#pragma 预处理...............................................................................................................67 3.6.8,#pragma pack........................................................................................................ 69 3.6.8.1,为什么会有内存对齐?........................................................................... 70 3.6.8.2,如何避免内存对齐的影响....................................................................... 70 3.7, #运算符..............................................................................................................................72 3.8,##预算符..........................................................................................................................72 第四章指针和数组.........................................................................................................................74 4.1,指针.................................................................................................................................74 4.1.1,指针的内存布局...................................................................................................74 4.1.2,“*”与防盗门的钥匙............................................................................................. 75 4.1.3,int *p = NULL 和*p = NULL 有什么区别?.................................................... 75 4.1.4,如何将数值存储到指定的内存地址.................................................................. 76 4.1.5,编译器的bug?....................................................................................................77 4.1.6,如何达到手中无剑、胸中也无剑的地步.......................................................... 78 4.2,数组.................................................................................................................................78 4.2.1,数组的内存布局...................................................................................................78 4.2.3,数组名a 作为左值和右值的区别.......................................................................79 4.3,指针与数组之间的恩恩怨怨..........................................................................................80 4.3.1,以指针的形式访问和以下标的形式访问.......................................................... 80 4.3.1.1,以指针的形式访问和以下标的形式访问指针....................................... 81 4.3.1.2,以指针的形式访问和以下标的形式访问数组....................................... 81 4.3.2,a 和&a 的区别...................................................................................................... 81 4.3.3,指针和数组的定义与声明...................................................................................83 4.3.3.1,定义为数组,声明为指针....................................................................... 83 4.3.3.2,定义为指针,声明为数组....................................................................... 85 4.3.4,指针和数组的对比...............................................................................................85 4.4,指针数组和数组指针......................................................................................................86 4.4.1,指针数组和数组指针的内存布局...................................................................... 86 4.4.3,再论a 和&a 之间的区别.....................................................................................87 4.4.4,地址的强制转换...................................................................................................88 4.5,多维数组与多级指针......................................................................................................90 4.5.1,二维数组...............................................................................................................91 4.5.1.1,假想中的二维数组布局........................................................................... 91 4.5.1.2,内存与尺子的对比....................................................................................91 4.5.1.3,&p[4][2] - &a[4][2]的值为多少?........................................................... 92 4.5.2,二级指针...............................................................................................................93 4.5.2.1,二级指针的内存布局............................................................................... 93 4.6,数组参数与指针参数......................................................................................................94 4.6.1,一维数组参数.......................................................................................................94 4.6.1.1,能否向函数传递一个数组?................................................................... 94 4.6.1.2,无法向函数传递一个数组....................................................................... 96 4.6.2,一级指针参数.......................................................................................................97 4.6.2.1,能否把指针变量本身传递给一个函数................................................... 97 4.6.2.2,无法把指针变量本身传递给一个函数................................................... 98 4.6.3,二维数组参数与二维指针参数.......................................................................... 99 4.7,函数指针........................................................................................................................100 4.7.1,函数指针的定义.................................................................................................100 4.7.2,函数指针的使用.................................................................................................101 4.7.2.1,函数指针使用的例子............................................................................. 101 4.2.7.2,*(int*)&p ----这是什么?....................................................................... 102 4.7.3,(*(void(*) ())0)()------这是什么?.....................................................................102 4.7.4,函数指针数组.....................................................................................................103 4.7.5,函数指针数组的指针.........................................................................................104 第五章内存管理...........................................................................................................................107 5.1,什么是野指针................................................................................................................107 5.2,栈、堆和静态区............................................................................................................107 5.3,常见的内存错误及对策................................................................................................108 5.3.1,指针没有指向一块合法的内存........................................................................ 108 5.3.1.1,结构体成员指针未初始化..................................................................... 108 5.3.1.2,没有为结构体指针配足够的内存..................................................... 109 5.3.1.3,函数的入口校验......................................................................................109 5.3.2,为指针配的内存太小.....................................................................................110 5.3.3,内存配成功,但并未初始化.........................................................................110 5.3.4,内存越界............................................................................................................. 111 5.3.5,内存泄漏............................................................................................................. 111 5.3.5.1,告老还乡求良田......................................................................................112 5.3.5.2,如何使用malloc 函数.............................................................................112 5.3.5.3,用malloc 函数申请0 字节内存.............................................................113 5.3.5.4,内存释放..................................................................................................113 5.3.5.5,内存释放之后..........................................................................................114 5.3.6,内存已经被释放了,但是继续通过指针来使用............................................ 114 第六章函数.................................................................................................................................. 115 6.1,函数的由来与好处........................................................................................................116 6.2,编码风格........................................................................................................................ 116 6.2,函数设计的一般原则和技巧...........................................................................................121 6.4,函数递归........................................................................................................................123 6.4.1,一个简单但易出错的递归例子........................................................................ 123 6.4.2,不使用任何变量编写strlen 函数......................................................................124 第七章文件结构.........................................................................................................................127 7.1,文件内容的一般规则....................................................................................................127 7.2,文件名命名的规则........................................................................................................130

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧