Haste Makes Waste.

Thoughts are but dreams till their effects be tried. -- William Shakespeare

C++博客 首页 新随笔 联系 聚合 管理
  0 Posts :: 0 Stories :: 0 Comments :: 0 Trackbacks
共2页: 1 2 
@dell
会导致什么问题?怎么让人困惑?说话别不明不白的
@volnet
用mail吧,不习惯聊天
@volnet
互相学习,互相促进而已。你到我的博客文章里去找联系方式吧,哈哈
@volnet
两个风牛马不相及的东西被你说成相似——熊猫和小熊猫。

感觉你自己的理解还是比较混乱。
1、……到其所在*编译单元*的结束。如果“到其所在(待编译)的文件的末尾结束”,那头文件中定义的外部变量就会……基本没有作用。

2、extern表示被声明的variable或者函数在其他地方定义并分配存储空间了。如果使用了extern,就有可能不必include相应的头文件。

3、“如果外部变量的定义与变量的使用不在同一个源文件中,则必须在相应的变量声明中强制地使用关键字extern。”——声明/定义变量时,无论是全局还是局部变量,不带extern永远是定义。

“通常在对个别文件作出修改后,我们只需要重新编译那个文件”——这更多的是模块间的依赖问题。

“这一点给人的感觉static非常像C++/C#/Java中的private修饰符,即仅对当前文件(其它语言中可能并非文件)有效。”——你该好好理解一下OO了。static在C++中一种意思就是与C一样。C#有assembly的概念,其internal更像static,但又不完全像。Java我不熟,不过也绝不是你说的这样。private是访问权限修饰符(access permission modifier),而static是存储说明(storage class specifier),两者是*完全*不同的概念。——强烈要求你仔细阅读相关书籍以免误导大家。

char repeatVariableWithoutDefinition1; /*declear thrice no hurt*/——真的no hurt吗?

强调一点:编译单元和源文件是有区别的。
re: In the USA - 2[未登录] raof01 2008-08-15 10:06
地方大人少,当然可以一人一间,哈哈。
@杨粼波
同意。博主牛。
觉得模块划分粒度不够细。可以分成两个类,这样复用程度高一点:
1、m_szFreeList的每个表项可以封装成一个类。策略很多,找一个合适的就行。比如:
|head

-------------------------------------
|size|    |////|size|    |////|size|
|----|free|////|----|free|////|----|free
|next|    |////|next|    |////|next|
-------------------------------------
   |           ︿ |            ︿ |
   |           | |            | v
    -----------   ------------  NULL
当然,复杂性会有很大的增加,比如合并内存碎片。
2、用你的hash表来组织第一个类的对象。
最好不要用单件。

可以使用简化的slab来做内存池/对象池——虽然不支持可变长度对象,但其使用范围更广也更灵活。
怎么可能一样?
你试试成员是其他类对象的情况看看。如A和B两个类示范的。
还有各种资源比如打开的文件,进程描述符,线程描述符等等。
表达式的lvalue是不可修改的,可修改的只有其rvalue。因为当一个表达式具有lvalue时,它在内存中的位置是固定的,也就是lvalue是固定的。所谓修改表达式的值只是通过其lvalue来修改其rvalue。
比如
int i = 10;
假定i的地址为0x1000,那么i的lvalue是0x1000,rvalue是10,
i = 100;
则表示0x1000存放的内容也就是rvalue被修改成100,而不是i的lvalue——0x1000被修改成别的值,其内容为100。
如果:
“* 操作符应用与左值表达式,以表达式左值为地址,取出表达式类型的值,作为右值返回。”

那么:
int foo(int *p)
{
return (*p)++; // Or *p += 1;
}
如何解释?
re: 原子比较替换锁[未登录] raof01 2008-07-16 09:36
还有内核里的spinlock
没看过apue吧
正准备写一篇类似的东西。被你抢先了……
还有没有必要写呢?
re: 推荐 SICP[未登录] raof01 2008-06-24 09:13
@cuigang
谢谢!可我数学不行怎么办?
re: 推荐 SICP[未登录] raof01 2008-06-23 09:10
@cuigang
你强烈推荐的一定要试试!
不过不知道需要什么预备知识?我对于SICP没有概念。另外,这本书全名是什么?
4)越早让你的程序投入调试越好.
东拼西凑最容易导致调试时间过长。
这点我基本不同意。

1)程序不会出错,出错的肯定是人;如果程序出错了,那也一定是人的错误.
强烈同意!!!newbie与professional的区别之一就是newbie总认为是系统的错,professional总从自身找原因。
刚才吃西瓜时突然想到:base* p1=&derived(); 后,临时对象已不复存在,然而编译器依然会将该临时对象的内存区解析为base,然而vtbl中的内容依然指向derived::Print(),为base加上析构,这样vtbl先是指向derived::Print(),而后调用~base()时,该临时对象的类型变成了base,vtbl表项被纠正为指向base::Print()。
@control
同意你的观点。
博主曾说自己的C/C++水平足以应付工作。然而,我不得不说,有很多理解是错的,表面看起来可以工作,且例子也能论证你的观点,那只不过是碰巧了而已。而且总是以C的观点来看待C++,这是很危险的。
@创
“C++对我而言就是有STL带class能处理多态,继承的C. ”
最初的C++大体是这样,除了STL。
然而,现在还这么想的话,犯下这个错误是必然——C++的对象模型远不止C那么简单,背后有很多事情需要注意的。甚至,有时候构造函数是否为inline就决定了代码是否为二进制兼容。
re: 我眼中的构架 raof01 2008-06-06 08:48
我喜欢第六条!
re: 删除字符串中的子串 raof01 2008-06-05 17:51
@路缘
也没啥问题了——我没有仔细考虑,时间紧,我只拿了5分钟来写这个。
re: 删除字符串中的子串 raof01 2008-06-05 13:11
@路缘
看来没有唬住你。你的理解是没错的,呵呵。
除了del_substr(),别的还有问题吗?
re: 编译器产生的临时值 raof01 2008-06-04 16:23
你传递的是引用,上哪生成临时对象去?所以不是临时变量的问题,而是类型检查的事。如果提供了隐式转换,你的代码就没有问题,所以KDEVELOP不会抱怨。
这几行代码里面有写错误,不知道你看出来了没有?呵呵。希望你能改掉这些错误。
感觉博主对于传参方式(传值)没有理解。
函数原型有错误:无法返回该字符串。感觉下面会好一点:
char* del_substr(char* str, const char * substr);
说不用字符串操作函数,我就hack一把——自己写操纵字符串的库函数,呵呵……:
ssize_t Strlen(const char* str)
{
ssize_t len = 0;
while (*str++) ++len;
return len;
}

int StrCmp(const char* str1, const char* str2, ssize_t len)
{
for (int i = 0; i < len; ++i)
{
if (*(str1 + i) != *(str2 + i))
return (*(str1 + i) - *(str2 + i));
}
return 0;
}

char* del_substr(char* str, const char * substr)
{
char* temp = NULL;
ssize_t len = Strlen(substr);
while (*substr++ && *str++)
{
if (*substr == *str)
{
if (!StrCmp(substr, str, len))
{
temp = str + len;
while (*temp++)
{
*str++ = *temp;
}
break;
}
}
}
return str;
}
观点狭隘。我身边的程序员可都是高智商高情商的——与人打交道不够圆滑那是因为没有把所有的精力放到这上面。
C++ "*"三种意思:
1. 乘号
2. dereference运算符
3. 复合类型中声明/定义指针变量

关于多态:
编译时:模板、重载
运行时:通过虚表
运行时多态相关的概念:静态类型、动态类型。
个人观点,仅供参考
@啸天猪
数组名是lvalue。但lvalue不是object with name,而是内存区域的引用。这个问题我更倾向于cuigang的说法,虽然他用的是地址。
临时对象是右值,呵呵。
我对于lvalue和rvalue的理解基本上是错误的,呵呵,多谢cuigang和猪了。
@cuigang
仔细查阅了一些资料,发现对于lvalue和rvlaue的说明各有不同。找了两个比较经典的说法,共同参考一下。下面是在comp.lang.c++.moderated上找到的(为避免断章取义,贴全文):
The simplest explanation I know is that an rvalue, in current C++, is an *expression* that produces a value, e.g. 42, and an lvalue is an *expression* that just refers to some existing object or function[1]. Hence the acronym "locator value"[2], which however is still misleading because an lvalue is simply not a value. Better would be *rexpression* versus *lexpression*, and even better, just value versus reference (unfortunately the term "reference" is already hijacked).

"object" versus "value": in C++ the basic definition of "object" is a region of storage, i.e. anything that actually occupies storage, while a pure value such as 42 doesn't necessarily occupy any storage. A value (an rvalue) can be an object, though. If it is, then it's a temporary object.

C++ allows you to call member functions on a class type rvalue, i.e. on a temporary class type object.

The ability to call member functions on (class type) rvalues, together with C++'s treatment of assignment operator as a member function (automatically generated if needed and none defined), means that you can assign to class type rvalues. However, C++ does not regard that rvalue to be *modifiable*: to be
well-defined, the assignment must do something else than modifiying the object assigned to (and typically we indicate that by declaring the assignment operator const). §3.10/14 "A program that attempts to modify an object through a nonmodifyable lvalue or rvalue expression is ill-formed".

Fine point: §3.10/14 means that rvalue-ness transfers to parts of an rvalue, which are thereby also considered rvalues. However, at least the two compilers I use don't seem to know that rule. Comeau Online does.

I'm not sure if the explanation above holds up with respect to C++0x rvalue references. rvalue versus lvalue got a lot more complicated in C++ than in original C. Perhaps it's even more complicated in C++0x, I don't know. :-)

Cheers, & hth.,
- Alf

Notes:
[1] Amazingly that's also the general definition the standard starts out with, before going into details: §3.10/2 "An lvalue refers to an object or function", however, it would have helped much if the word "expression" was explicitly included there, not just by being mentioned in the preceding paragraph.
[2] Unfortunately the C++ standard doesn't use or even mention the acronym "locator value". This acronym comes from the current C standard. And ironically the C++ standard mentions, by contextual placement, the original old C acronym of "left hand value", in §3.10/4: "built-in assignment operators all expect their left hand operands to be lvalues".

Programming Cpp的解释:
http://etutorials.org/Programming/Programming+Cpp/Chapter+3.+Expressions/3.1+Lvalues+and+Rvalues/

你的解释更接近真相,呵呵,不过我还是不同意地址一说,用引用会比较好一些。要不你整理一下,就lvalue和rvalue专门写一篇?

看来俺还得多看看标准啊。
我的C++标准丢了,给发一个?raof01@gmail.com。
@cuigang
我始终不同意这句话:“表达式的左值是它的地址,右值是该地址所存储的内容。”因为无论地址还是内容,都是对象。而且按照你这句话,x = x + 1;第一个x是个地址,第二个x是其内容,假设x是T类型,那么上述表达式就应该理解为=左边是个地址,也就是T*,对吧?矛盾就来了,你把T类型的值赋给了T*。
“虽然言语之中仍然为自己辩护,不过大家观点毕竟更加接近了”——刚才又仔细看了一遍你的文章,我坚持我第一个评论里的观点,除了“&操作符能作用于左值和右值”这个错误。
我认为:因为你的第一个观点是全文的核心,所以我们之间还存在巨大的分歧。
@cuigang
你别无奈啊,给个理由先。
我的依据是:左/右值指的是表达式。单纯就x这个表达式来说,它是个左值,无论在=左边还是右边。
@cuigang
你举的例子x=x+1;其中x无论是在左边还是右边都是左值,表达式"x+1"才是右值。
@cuigang
请注意我的用词(有咬文嚼字之嫌,见谅):返回、对象、表达式。对象包括很多:指针、字面常量、临时对象……我认为我们之间的分歧在于你把我说的对象细分了。

“但 & 操作符的确只能应用于有左值的表达式”——你是对的,我的错误。

“至于你链接的文章,请恕我未能洞悉,不知里面哪里提到 解引用操作符可以用于右值,或者隐含此意味。”——实际我想说明的就是“但是间接寻址(indirection)反而说明了你的观点,它是将指针变量的右值作为地址来访问指向物,类似的有‘.’,‘->’运算符。”,因为我把指针当作对象的一种。

“我说指向数组的指针费解,不是说我不理解,只是说大多数人实际中难以见到,不好理解,如果你可以理解,你可以说说它和多维数组 arr[][] 的 指针 arr[2] 有什么区别。”我相信你理解了,否则也不会写出这么有深度的文章。T arr[]中arr的类型是T[],&arr的类型就是T(*)[];但是,T arr[][]中arr的类型是T * arr[],&arr的类型是T**——最后这点是因为C中二位数组是线性存储的,不是我们所理解的二维矩阵。

——向你的认真致敬!呵呵
sorry,上面有个错误:a[10] = x; 改为 a[0] = x;
@啸天猪
"左值未必都是可修改的,例如数组名就是不可修改的左值":数组名不是左值。注意我说的话:*返回*可修改对象……数组名是一个* const,不是左值。简言之:int a[10];可以有int * p = a; a[10] = x;但不能有a = p;
“但是对于user defined type 的右值,在某些情况下是允许被修改;例如对于函数返回的临时对象,调用non-const member function是合法的”:临时对象不一定是右值。*返回*不可修改对象……
讨论就是讨论,没有骂人的,看来大家都是好人。哈哈,这里不错。
re: 对string类的思考 raof01 2008-04-11 12:18
虽然你的想法已经有很多人这么做了,不过我觉得你自己想出来也很了不起,敬仰啊。
几个错误:
左值:返回一个可修改对象的表达式称为左值
右值:返回一个不可修改对象的表达式称为右值
*操作符返回的对象可能是左值也可能是右值
&操作符可用于左值和右值
*操作符的操作数可以是右值(请参考“映射设备寄存器到内存”http://blog.chinaunix.net/u/12783/showart_385250.html
arr是T [100],那么&arr就是T (*)[100],没什么费解的
re: 猜猜看,id变成9了吗? raof01 2008-04-02 13:57
类型转换(非引用)必然会产生一个临时对象。所有的一切问题都可以归结到这里:
((TestStr)(*p_ts)).SetId(9);//产生non-const临时对象,SetId()操作的是临时对象,因此原对象不变
((TestStr&)(*p_ts)).SetId(9);//去掉原对象的const。可以写成const_cast<TestStr&>(*p_ts)).SetId(9)
((TestStr)(*p_ts)).id = 9; //GCC可以编译
(&((TestStr)(*p_ts)))->id = 9; //编译通过
re: 搭建通用构造器 raof01 2008-04-01 09:48
不错。不过我认为xObjectCreator不需要继承xBaseCreator——已经通过模板来得到一定的多态性了。
re: 不怕无知,但怕无畏 raof01 2008-03-26 15:15
@某Programmer
你的说法有失偏颇。有些时候可以通过一些技术上的细节问题来考interviewee,此时并不是要考他的记忆,而是看他的思考方式。也就是那句话:你的答案是错的,但我喜欢你的思考方式。
re: 不怕无知,但怕无畏 raof01 2008-03-21 09:32
有很多人学过几天C++,就敢在简历上写“精通C++”,这种人被BS了活该。另:应用程序员对于library的实现还是很陌生的,考虑的也不会很多,博主要求有点高。
打着C++旗号的C
re: 为二维数组循环赋值 raof01 2008-03-04 16:29
//时空性能还行,比楼主的代码难看多啦~~
template <size_t N1, size_t N2>
void Convert(int (&array)[N1][N2])
{
int all = N1 * N2;
int i = 0;
int j = -1;
int direction = 0;
int val = 0;
while(val < all)
{
if (0 == direction)
{
++j;
if (j < N2 && -1 == array[i][j])
{
array[i][j] = val;
}
else
{
direction = 1;
--j;
}
}
if (1 == direction)
{
++i;
if (i < N1 && -1 == array[i][j])
{
array[i][j] = val;
}
else
{
direction = 2;
--i;
}
}
if (2 == direction)
{
--j;
if (j >= 0 && -1 == array[i][j])
{
array[i][j] = val;
}
else
{
direction = 3;
++j;
}
}
if (3 == direction)
{
--i;
if (i >= 0 && -1 == array[i][j])
{
array[i][j] = val;
}
else
{
direction = 0;
++i;
--val;
}
}
++val;
}
}
re: 单链表逆序输出 raof01 2008-02-29 12:47
先逆序再输出比递归高效。
N个节点,递归就存在N次函数调用,而先逆序再输出就2次调用(分两个函数写的话)——当然不包括调用其他函数。其他函数如print()调用次数是固定的。假设N巨大,还有可能出现栈问题,而先做逆序仅仅是指针的赋值循环。
实际上,引用的底层实现就是指针。可以将引用看作无需dereference就可使用指向的内存的指针。
re: 据说是Google面试题 raof01 2008-02-24 21:55
楼主——麻烦你给出解题思路好不好?光看代码太费劲了,而且我不喜欢看代码。
共2页: 1 2