读书人

最近写的一些东西,该怎么解决

发布时间: 2012-02-19 19:43:39 作者: rapoo

最近写的一些东西
贴出来的都是当前最新版本,根据最新进展,会在blog更新。

前三楼莫占,等我把后面几篇贴出来先。

列表:
1.关于c++名字解析的一个问题
2.关于程序设计语言的一些看法的摘录或自己的分析
3.tra---一种应用于泛型编程的模式
4.结合性,优先级,声明
5.求值时的未定义行为

[(1)这个比较初级;(2)可能会长期更新;(3)其实就是模板多态的一种应用,写了一个使用不同的二叉查找树或者平衡查找树,能提供map,set及其多重版本的和stl有一定程度兼容的数据结构。(4)(5)中关于自动机和语言的理论的术语的使用并不准确,甚至是错误的,只要懂得起意思就是了。只是说一下,表示一下,并没有严格的证明。]



关于c++名字解析的一个问题

编译环境是
gcc version 4.5.1 (tdm-1)

Microsoft Visual Studio 2010 10.0.30319.1 RTMRel

操作系统是
Windows7 旗舰版

问题:
#include <algorithm>
using namespace std;
namespace X
{
struct Y{int v;};
};
bool operator < (X::Y a, X::Y b)
{
return a.v < b.v;
}
int main()
{
X::Y data[5];
sort(data, data+5);
return 0;
}
编译无法通过。

主要错误提示,无法找到对应的operator <。

1.一个直观的感觉是sort在algorithm里有了,在定义里,找不到对应的operator <。
其实不然,因为模板的实例化点不在algorithm里。所以,即使把#include <algorithm>
搬到operator <后是不行的。

2.试图错误重现:

C/C++ code
#include <algorithm>#include <iostream>using namespace std;namespace X{ struct Y{int v;};};bool operator < (X::Y a, X::Y b){ return a.v < b.v;}namespace Z{ int foo(X::Y a) {  return a < a; }}int main(){ X::Y data[5]; cout << Z::foo(data[0]) << endl; return 0;}
没有报错
交换operator < 和namespace Z后报错,这很显然。
回想到sort是函数模板,于是把foo改成模板形式:
C/C++ code
#include <algorithm>#include <iostream>using namespace std;namespace X{ struct Y{int v;};};namespace Z{ template<typename T> int foo(T a) {  return a < a; }}bool operator < (X::Y a, X::Y b){ return a.v < b.v;}int main(){ X::Y data[5]; cout << Z::foo(data[0]) << endl; return 0;}
即使改变顺序也不会报错,原因是实例化点在operator <后面。

结论:试图错误重现失败。

3.进一步错误重现:
把gcc中的__insertion_sort copy出来放到namespace Z里,同时包含必要的头文件,对
代码中必要的部分进行修改,但是没有本质上的修改。
但是没有出现期待中的错误。

结论:进一步错误重现失败。

4.使用vc10发现在utility, memory等文件中总共有4个侯选的operator <。
通过把这四个operator <注释掉,没有出现错误。

5.更进一步错误重现:
C/C++ code
#include <algorithm>#include <iostream>using namespace std;namespace X{ struct Y{int v;};};namespace Z{ template<typename T> struct dummy{}; template<typename T> bool operator <(dummy<T>, dummy<T>){return 1;} template<typename T> int foo(T a) {  return a < a; }}bool operator < (X::Y a, X::Y b){ return a.v < b.v;}int main(){ X::Y data[5]; cout << Z::foo(data[0]) << endl; return 0;}
结果:出现期待中的错误。

6.结论:
在同一scope里查找失败时,不会在外一层scop中查找。

7.解决方案1
C/C++ code
namespace X{ struct Y{int v;}; bool operator < (Y a, Y b) {  return a.v < b.v; }};
对某个类型的操作,应该放在该类型所在的scope里,这样可以通过ADL查找到对应的名字。
如果放在该scope的外层,在该scope里的同名的会阻止在外层中的名字解析:名字污染。

8.解决方案2
C/C++ code
#include <algorithm>#include <iostream>using namespace std;namespace X{ struct Y{int v;};};bool operator < (X::Y a, X::Y b){ return a.v < b.v;}int main(){ X::Y data[5]; bool (*cmp)(X::Y, X::Y) = &operator < ; sort(data, data+5, cmp); return 0;}
很明显,从执行效率,代码优美程度上讲都不如解决方案1。
如果是使用别人的库,原有的compare不满足要求,同时又不希望自己写的cmpare污染原有名字空间


可以选择这种。








关于程序设计语言的一些看法的摘录或自己的分析

指针的实现:
程序员们常常把指针等同于地址(一些教科书里也这样说),但这实际上是一个误
解。指针是一个高级概念,就是对于对象的引用;地址是一个低级概念,是内存单元的
位置。指针常常通过地址实现,但并不总是这样。在具有分段存储器体系结构的机器上,
指针可以由一个段标识和一个段内偏移量组成。在那些企图捕捉所有悬空引用的语言里,
指针可能包含一个地址和一个访问关键码。

Michael L. Scott, 裘宗燕(译),程序设计语言--实践之路 第2版,电子工业出版社:369






指针和数组:
许多C程序里用指针而非下标方式在数组元素中做迭代。在新型的优化器开发出来之
前,基于指针去遍历数组常常能消除多余的地址计算,从而得到速度更快的代码。然而,
对于新型编译器而言,相反的说法可能更正确,多余的地址计算可以被识别为公共表达
式,对下标段长霜些优化比对指针做更容易些。特别的,如我们在第15章里看到的,指
针将使优化程序确定两个左值是否相互为中坚力量名的问题变得困难多了。
今天继续使用指针算术,更多的就是个人的口味问题了。一些C程序员认为基于指针
的算法比基于数组的算法更优美。当然,由于数组总是被作为指针传递给子程序,所以按
指针风格定义子程序也很自然。

Michael L. Scott, 裘宗燕(译),程序设计语言--实践之路 第2版,电子工业出版社:377




ISO/IEC:14882(2003)

C++中的Object
1.8.1
The constructs in a C + + program create, destroy, refer to, access, and manipulate objects. An object is a
region of storage. [Note: A function is not an object, regardless of whether or not it occupies storage in the
way that objects do. ]


C++中的实体
3:3
An entity is a value, object, subobject, base class subobject, array element, variable, function, instance of a
function, enumerator, type, class member, template, or namespace.


C++中的名字,变量
3:4
A name is a use of an identifier (2.10) that denotes an entity or label (6.6.4, 6.1). A variable is introduced
by the declaration of an object. The variable’s name denotes the object.


C++中名字的引入,作用,等价性
3:5
Every name that denotes an entity is introduced by a declaration. Every name that denotes a label is introduced
either by a goto statement (6.6.4) or a labeled-statement (6.1)Blank page.

3:6
Some names denote types, classes, enumerations, or templates. In general, it is necessary to determine
whether or not a name denotes one of these entities before parsing the program that contains it. The process
that determines this is called name lookup (3.4).

3:7
Two names are the same if
— they are identifiers composed of the same character sequence; or
— they are the names of overloaded operator functions formed with the same operator; or
— they are the names of user-defined conversion functions formed with the same type.


在N3126草案中的对比
1.8.1
The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is a
region of storage. [ Note: A function is not an object, regardless of whether or not it occupies storage in the
way that objects do. —end note ]

3:3
An entity is a value, object, reference, function, enumerator, type, class member, template, template specialization,
namespace, parameter pack, or this.

[新加的:reference,parameter pack,this]
[去掉的:base class subobject,variable,instance of a function]
[个人认为新加就是以前思考不周到的地方,而去掉的东西中比较重要的是variable,从新老标准的第4条可以看出,确实不应该放在里面]

3:4
A name is a use of an identifier (2.10) that denotes an entity or label (6.6.4, 6.1). A variable is introduced
by the declaration of an object. The variable’s name denotes the object.


3:5
Every name that denotes an entity is introduced by a declaration. Every name that denotes a label is
introduced either by a goto statement (6.6.4) or a labeled-statement (6.1).


3:6
A variable is introduced by the declaration of a reference other than a non-static data member or of an
object. The variable’s name denotes the reference or object.

[变量通过声明一个引用(对非static数据成员)或声明一个object引入。变量的名字指代了这个引用或者对象。]

3:7
Some names denote types or templates. In general, whenever a name is encountered it is necessary to
determine whether that name denotes one of these entities before continuing to parse the program that
contains it. The process that determines this is called name lookup (3.4).



3:8
Two names are the same if
— they are identifiers composed of the same character sequence, or
— they are operator-function-ids formed with the same operator, or
— they are conversion-function-ids formed with the same type, or
— they are template-ids that refer to the same class or function (14.4), or
— they are the names of literal operators (13.5.8) formed with the same literal suffix identifier.


引用上面那么多标准(或草案)条目,最主要的问题是弄清楚什么是对象(并不是OO中所涉及的对象),什么是变量。

Alexander, Stepanov, Paul McJones, Elements of Programming, 机械工业出版社,第4页(翻译过来的)
内存是一些词的集合,并且每个词拥有地址和内容。
对象是一个具体对象作为一个值在内存中的表示。(注:这里限制为具体对象了,但是在后文中说抽象对象也可以表示,其中有些原因,但是不详细追究)
在书的前面提到:
值类型是指某个species(具体的或者抽象的)和一些数据(在前文定义为一个限的01序列)的对应。对应到指定实体的数据称为
这个实体的表示,同时这个实体称为该数据的解释。我们提到某个数据,连同其解释,称之为值。

使用对象的原因:
1.对象能对可变的具体实体进行建模,比如在某个关于薪水的应用程序中的雇佣记录;
2.对象提供了实现作用在值上的函数的强有力的手段,比如用迭代法求浮点数的平方根的过程;
3.Computer with memory constitute the only available realization of a universal computational device.


继续引用
Robert W.Sebesta,张勤(译),王方矩(译),《程序设计语言原理》,第7版,机械工业出版社,5.3,136页

程序的变量是指计算机的存储单元或对计算机一系列存储单元的抽象。程序人员常常认为变量是存储地址的名字,
但是变量比仅是名字具有更重大的意义。从机械语言到汇编语言的发展,在很大程度上是用名字替代绝对数字的
存储地址的发展,这使得程序可读性更好,因而也就更容易编写和维护。因为将名字转移为实际地址的翻译器也
选择这些地址,所以这一步回避了绝对地址的问题。
可以使用6种属性来刻画一个变量:名字,地址,数值,类型,生存期,作用域。尽管这对于一种看似简单的概念
似乎太过复杂,但正是这6种属性提供了一种最清晰的方式来解释变量的各个方面。


[
“变量是存储地址的名字”
将这句话缩句:变量是名字。或者反来说:存储地址的名字是变量。
这样变量的定义是一个名字,其内涵是指代存储地址。这样定义同时和变量名的概念混淆。
持有这种说法的人“更关心在生成目标代码的时候,名字和存储位置的对应关系。”,还似乎洋洋得意地看到了
编译器中维护名字和位置的过程,停留在面向底层目标编程的阶段。
正如书中的定义,该理解忽略了很多其它属性。

但是书中说,作用域是变量的属性。我认为,这条属性应该是名字的属性,同时和其它名字(一般是同名)发生关系。
作用域粗略地说是名字的可见范围,当两个scope包含关系时,内部名字隐藏外部相同名字(即:外部名字的可见范围
被内部相同的名字影响了)(并不保证所有的语言都采用这条规则)
]
(2011.01.07修改)


[解决办法]
这个必须顶起。。
[解决办法]
路过。。。。。。。。。。。。。。
[解决办法]
.............
[解决办法]
路过。。。。。。。。。。。。。。
[解决办法]
呵呵,好久不见楼主了,支持一下^_^
[解决办法]
楼主结帖率:101.82%,怎么做到的

[解决办法]
收藏慢慢看~~
[解决办法]
我也好奇,楼主的结贴率 。。。

先收藏。。。
[解决办法]
撸过...探索与总结思考的精神,竟然连编译原理都搬出来了,学习.
[解决办法]

[解决办法]

探讨
引用:
楼主结帖率:101.82%,怎么做到的

有个贴子被当成广告删除了,后来恢复,于是在结贴后,结贴数大于发贴数了。
这说明数据库并没有自动维护这方面的一致性。

[解决办法]
楼主真是个猛男
[解决办法]
C/C++ code
namespace Z{ template<typename T> int foo(T a) {  return a < a;//这不永远为假么? }}
[解决办法]
飞雪大侠~@!
[解决办法]

[解决办法]
mark.........


[解决办法]

[解决办法]

[解决办法]
关于c++名字解析的一个问题 ---这个在c++编程思想的第二卷中就有说明,我记得好象是~~~
[解决办法]
泛型正在学
[解决办法]
飞雪~飞雪!你老霸道了。。。
[解决办法]
你想写的东西好多啊?lz加油啦..
[解决办法]
楼主散分么~~
[解决办法]
感谢楼主的无私奉献


[解决办法]

[解决办法]

[解决办法]
受益匪浅
[解决办法]
说看完了是鬼话。收藏慢慢看
[解决办法]
慢慢品吧,,,
[解决办法]
基本功是王道~~
[解决办法]
飞雪。飞雪,飞雪。飞雪。。。。。。。。。。。。。
[解决办法]
这怎么看得完啊
[解决办法]
这个必须顶,何况还有分。。。
楼主是好人
[解决办法]

[解决办法]

探讨
感谢楼主的无私奉献

[解决办法]
楼主是好人啊。。。。。。。。。。。。。。
[解决办法]
读完了,受益匪浅,再顶楼主。
[解决办法]
好贴,飞雪 你是打算一直更新这个帖子吗?
[解决办法]
飞雪,离我们一直很远。。。
[解决办法]
还不错哦
[解决办法]
这个是好东西~~
[解决办法]
飞雪大侠,我就想知道,我咋样才能像你一样。这和天赋有没有关系?
[解决办法]
顶一下,这个是猛料!
[解决办法]
楼主,赶紧散分吧
[解决办法]

[解决办法]
晕,好多啊
[解决办法]

[解决办法]
会仔细的看完。。。。
[解决办法]
支持大神们的分享。
我也要变成程序专家。
------解决方案--------------------


收下了。
[解决办法]
高人,研究一个方向就很系统。
[葱花饼]

读书人网 >C++

热点推荐