求侯捷翻译的C++ Primer 3e

antijpn 2003-07-08 08:28:58
求侯捷翻译的C++ Primer 3e,潘爱民的我有了,现在想两本对照着看。
...全文
105 51 打赏 收藏 转发到动态 举报
写回复
用AI写文章
51 条回复
切换为时间正序
请发表友善的回复…
发表回复
antijpn 2003-07-21
  • 打赏
  • 举报
回复
让我好好想一下
另外,我想问问chinajiji,C++ Primer里面的那段话具体的意思到底是什么呢?
还有,那个special edition的The C++ Programming Language哪里有啊?我现在手上只有3rd Edition的The C++ Programming Language
cloudtarget 2003-07-20
  • 打赏
  • 举报
回复
www.codestudy.net
找一找吧
ckacka 2003-07-20
  • 打赏
  • 举报
回复
chinajiji(菜鸟叽叽)
^_^,被我抓住了,散布反动言论
tttzms 2003-07-19
  • 打赏
  • 举报
回复
const int cival=1;
int *pci=(int*)&cival;
*pci=2;
cout<<cival;
好像在C++.net 下出来的结果是2啊,不知怎么理解
biser 2003-07-18
  • 打赏
  • 举报
回复
www.pdown.com自己下吧。
chinajiji 2003-07-18
  • 打赏
  • 举报
回复
我找到了,这篇文章在这里:
http://www.cuj.com/documents/s=7988/cujcexp1912alexandr/alexandr.htm

www.cuj.com 可是世界最好的C++期刊网站之一哟,比CSDN上的C++论坛强100倍.
chinajiji 2003-07-18
  • 打赏
  • 举报
回复
CSDN太烦了,长一点的文章都不能一次贴完,

你自己到http://www.cuj.com/experts/
去找吧,文章叫Generic<Programming>: Move Constructors
作者:Andrei Alexandrescu(这个牛人很有名哟!)
chinajiji 2003-07-18
  • 打赏
  • 举报
回复
const int &ref = 123;
上面这句是正确的,但123并不是可以寻址的.因为123是个常数.
当然,你从编译器实现的角度来看,ref是一个临时变量的引用,而这个临时变量是可以寻址的.这种说法也是对的.
const int &ref = 123;
等价于:
int temp = 123;
const int* const pRef = &temp;

<<The C++ programming language>>关于Temporary Objects 的描述见:
10.4.10 Temporary Objects P254(English version Special Edition)

引用参见:
5.5 References P97.

顺便向你推荐一篇大师的文章:

--------------------------------------------------------------------------------

Generic<Programming>: Move Constructors
Andrei Alexandrescu

--------------------------------------------------------------------------------

As I'm sure you know very well, creating, copying around, and destroying temporary objects is the favorite indoor sport of your C++ compiler. Temporaries get created at the drop of a hat, and unfortunately that considerably impacts the performance of C++ programs. Indeed, temporaries are often credited as one of the top sources of inefficiency in C++ programs [1].

It would be nice if you could write:

vector<string> ReadFile();
vector<string> vec = ReadFile();

or:

string s1, s2, s3;
...
s1 = s2 + s3;

Alas, if you care about efficiency, you need to refrain from using such code. The temporaries created by ReadFile() and by operator+, respectively, will be copied to the destination and then thrown away ... what a waste!

To solve this, you need to rely on less elegant conventions. For example, you might pass the destination as an argument to the function:

void ReadFile(vector<string>& dest);
vector<string> dest;
ReadFile(dest);

Quite annoying. Worse, operators don't give you that option, so if you want to deal with large objects efficiently, you have to limit yourself to operators that don't create temporaries:

string s1, s2, s3;
...
s1 = s2;
s1 += s3;

These awkward idioms often creep up within large teams working on large programs, imposing a continuous annoyance that curbs the joy of writing code and adds to the total number of lines. Wouldn't it be nice if we could return values from functions, use operators, and pass around temporaries, in confidence that time is not wasted on this create/copy/destroy spree?

Wouldn't it?

Actually it's not about "would be nice" only. There is huge community pressure to solve the unnecessary copying problem. The interest in the subject is staggering. A formal proposal for a language-based solution has already been submitted to the standardization committee [2]. Discussions are ravaging the Usenet, and the article you're now reading has been intensely reviewed.

This article shows you how you can address the problem of unnecessary copying in existing C++. There is no 100% satisfactory solution, but a remarkable degree of purity can be achieved. We will build together, step by step, a powerful framework that helps eliminate unnecessary copying of temporaries from your programs. The solution is not 100% transparent, but it does eliminate all unnecessary copies, and is encapsulated enough to serve as a reliable placeholder until years from now when a cleaner, language-based, approach will hopefully be standardized and implemented.

Temporaries and the "Move Constructor"
After fighting temporaries for a while, people have realized that eliminating the actual temporaries is not really the point in most cases. Most of the time, the point is to eliminate unnecessary copying of temporaries. Allow me to detail this issue a bit.

Most "expensive-to-copy" data structures store their data in the form of pointers or handles. Typical examples are: a String type that holds a size and a char*, a Matrix type that holds a couple of integral dimensions and a double*, or a File type that stores a handle.

As you see, the cost in copying String, Matrix, or File does not come from copying the actual data members; it comes from duplicating the data referred to by the pointer or the handle.

So given that our purpose is to eliminate copying, a good way of doing that is to detect a temporary. In cynical terms — given that an object is a goner anyway, we might just as well use it as an organ donor while it's still fresh.

But what's a temporary, by the way? We'll come up with a heretic definition:

An object is considered temporary in a context if and only if the only operation executed on that object upon exiting that context is the destructor.

The context can be an expression or a lexical scope (such as a function body).

The C++ Standard doesn't define temporaries, but it assumes that they are anonymous temporaries (such as the values returned by functions). By our (more general) definition, named stack-allocated variables defined inside a function are temporary all right. We'll later use this insight to our advantage.

Consider this run-of-the-mill implementation of a String class:

class String
{
char* data_;
size_t length_;
public:
~String()
{
delete[] data_;
}
String(const String& rhs)
牋 : data_(new char[rhs.length_]), length_(rhs.length_)
{
std::copy(rhs.data_, rhs.data_ + length_, data_);
}
String& operator=(const String&);
...
};

Here the cost of copying consists largely of duplicating data_, that is, allocating new memory and copying it. It would be so nice if we could detect that rhs is actually a temporary. Consider the following pseudo-C++ code:

class String
{
... as before ...
String(temporary String& rhs)
: data_(rhs.data_), length_(rhs.length_)
{
// reset the source string so it can be destroyed
// don't forget that destructors are still executed
// on temporaries
rhs.data_ = 0;
}
....
};





antijpn 2003-07-18
  • 打赏
  • 举报
回复
chinajiji再帮我看看啊!
antijpn 2003-07-16
  • 打赏
  • 举报
回复
还有,对于您的夸奖,我十分感谢,可惜在中国,哎……总是被人说成钻牛角尖,还老受批评,sigh……
antijpn 2003-07-16
  • 打赏
  • 举报
回复
1. const int *p 与int * const p的区别;
答:const int *p是定义一个指针p,它指向const int型的数据,当然它也可以指向int型数据,但是不能通过p来修改它所指向的对象的值
int *const p是定义一个指针p,p本身是常量,但是这个定义没有意义,因为它没有初始化,编译器会报错(至少BCB5.5 Complier报错了),它指向一个int型的数据

2. const 与临时对象的区别与联系.
答:这个不太清楚,希望chinajiji给我解释一下,我的问题好像就在于这里

3. 变量的值与地址.
答:好像根本没什么关系吗?如果一定要说有的话,值是存在于地址里面的

4. 什么叫常量?
答:本身不可改变的量,譬如1,'a',1.5等,或者由程序员定义的常量

还有,你猜得一点不错,我就是在自学,可惜身边没有人能讨论(没有已经学成C++的人,也没有正在学的人),只好上网讨论了

你说的临时对象的处理,哪里有介绍的文章吗?

看来我的E文真的有问题,“我们的引用不是指向一个常量指针”我才看出来,我认为你的应该是对的,潘又错了(说不定是张)。你替我解释一下这句话的意思吧

“上面这句是正确的,但123并不可以可以寻址的.”后面半句看不懂啊

再帮我看看吧,感激不尽!


softworm163 2003-07-15
  • 打赏
  • 举报
回复
说得这么过瘾,我也来说两句:
P527
L17,L24
潘喜欢把intergral翻译成有序类型,
可是人家intergral本身就是整数的意思!
而候捷的C++ PRIMER ANSWER了是译成整数型别。


难以想像为什么要译成为有序类型。。。。。。
chinajiji 2003-07-15
  • 打赏
  • 举报
回复
另外,我对你这么好一个学生感到可惜,被中国这么差的教育环境浪费了,你是一个有思考能力的好学生.

你说:
还有,我的“不过要一个引用指向一个const对象,必要条件是这个const对象可以寻址”错在哪里呢?我觉得好像是对的啊?
我之说所以认为你的说法是错误的,是因为:
const int &ref = 123;
上面这句是正确的,但123并不可以可以寻址的.
你可能会说:ref实际上是指向一个临时变量的,这个临时变量是可以寻址的.
如果这样说当然是正确的.你说从编译器的实现上来看的,我是从语法上来看的.
如果从编译器的实现来看,你的说法当然正确,因为引用本质就是一个const 指针.


chinajiji 2003-07-15
  • 打赏
  • 举报
回复
你下面的这段代码我以前和一个网友讨论过.
const int cival=1;
int *pci=(int*)&cival;
*pci=2;
cout<<cival;

之所以cout << cival 输出为1而不是2,是因为cival是const的内建类型,
cival的值在编译期定死为1,也说是说,编译器在定义const int cival=1;
后,凡是遇见cival都用1替换之,这时const int 的行为很象C中的宏替换.如果是非const int,遇见cival则会去寻找cival变量所在内存中的值.

“我们的引用不是指向一个常量”是指&ival(即ival的地址)是一个常量指针.
也就是说&ival不可变量.

如果我们把C++ primer 中的那个例子改变如下:
const int ival = 1024;
const int *p = &ival;
// ok!
const int *&pi_ref = p;

我觉得你在理解上走进死胡同了,下面几个概念你必须弄清:
1. const int *p 与int * const p的区别;
2. const 与临时对象的区别与联系.
3. 变量的值与地址.
4. 什么叫常量?
你有打破沙锅问到底的精神很好,我感觉你可能是在自学,没有好的老师指点.
你的问题焦点我还是没有很好理解.
我要提醒的是:
1.除了对const对象的引用在定义时必须加const以外,对临时对象的引用也必须加const.
2.临时对象不是一个简单的话题,各个编译器对临时对象的具体处理是有区别的.
3.潘版<<C++primer>>翻译断句上有问题,他说“我们的引用不是指向一个常量”,
应该是:“我们的引用不是指向一个常量指针”
antijpn 2003-07-15
  • 打赏
  • 举报
回复
The C++ Programming Language我有,这个在哪一节?

还有,我的那个例子只是要证明临时变量并没有const属性,你可以再看这个:
const int cival=1;
int *pci=(int*)&cival;
*pci=2;
cout<<cival;
这个地输出结果就是1,而不是2,这样的话可以证明,常量就是常量,无法更改就是无法更改

那你说说C++ Primer里面的那个“我们的引用不是指向一个常量”是什么意思吧,我已经困惑了快一个月了

还有,我的“不过要一个引用指向一个const对象,必要条件是这个const对象可以寻址”错在哪里呢?我觉得好像是对的啊?
chinajiji 2003-07-15
  • 打赏
  • 举报
回复
你的这句话是错误的:
不过要一个引用指向一个const对象,必要条件是这个const对象可以寻址(
////////////////////////////
对于引用,我觉得《The c++ programming language>>中讲得很好,你可以找来看一看。
chinajiji 2003-07-15
  • 打赏
  • 举报
回复
首先,你的例子:
const int &i_ref=1;
int *p_iref=(int*)i_ref;
*p_iref=2;
cout<<i_ref;
这个输出的结果就是2,而不是1。这足以证明i_ref指向的临时变量并不是常量。
//////////////

之所以会产生看似矛盾的现象,是因为你用了强制类型转换.对于强制类型转换结果由用户负责.

除了对const对象的引用在定义时必须加const以外,对临时对象的引用也必须加const.
临时对象从语义上来讲是const的,虽然它有可能被改变.
<<C++primer>>上的那段话没有错,你对临时对象理解有点问题.
注意VC6.0,VC7.0,gcc对临时对象的处理有差异,以前有人在csdn上讨论过这个问题,不过时间久了,我也找不到这个贴子了。
fantasyCoder 2003-07-14
  • 打赏
  • 举报
回复
配套练习才是侯杰翻译的。。。。。
antijpn 2003-07-14
  • 打赏
  • 举报
回复
我有检查了一下,我发现我的观点的确有错误。不过和你举的例子没关系。
引用的确可以指向一个const对象,但是这个引用必须是const引用。
const int i=1024;
const int &i_ref=i;
cout<<"Address of i ="<<&i<<endl
"Address of i_ref ="<<&i_ref;
这样的话输出的地址是完全一样的。可见const引用的确可以指向const对象,不过要一个引用指向一个const对象,必要条件是这个const对象可以寻址(反正这个const对象不能是文字常量,这很重要,否则编译器就会跳出来声称临时对象!),还要是一个const引用,否则编译器又会跳出来生成临时对象。

但是你的例子有一个不恰当的地方,你是用了文字常量初始化引用,这样的话会导致编译器在栈中生成临时对象,引用指向这个临时对象,而这个临时对象并不是常量。它是可以被修改的!你可以看这段代码:
const int &i_ref=1;
int *p_iref=(int*)i_ref;
*p_iref=2;
cout<<i_ref;
这个输出的结果就是2,而不是1。这足以证明i_ref指向的临时变量并不是常量。

再看看你的代码,如果根据你的话,C++ Primer里面的那段话就是错误的了!看这句“我们的引用不是指向一个常量”,是不是和你的意思就完全相反了?

再看我的意思,根据我的理解,pi_ref就是指向内存中的临时变量了,而这个临时对象并不是一个常量,而是一个非常量指针。

我的疑问就在于C++ Primer是不是我这个意思?还是有其他意思?如果C++ Primer里面是我这个意思的话,那他的“我们的引用不是指向一个常量”,绝对可以算是一句废话!因为pi_ref定义的时候不满足引用指向const对象的第一个条件(就是“&ival”不可寻址,这个地址和文字常量属同一性质),既然根本不满足引用指向const对象的条件,他的那句话就没有必要写了,故称之废话。
请chinajiji看一下我的想法是否有道理,再说说你的想法,这对于我对引用的理解至关重要!
chinajiji 2003-07-14
  • 打赏
  • 举报
回复
你认为可不可能存在一个引用,它指向的是一个常量对象(无论是const引用还是非const引用,都包括在里面)。
////////////////////////////////////////////////
当然可以,比如:

#include <iostream>
using namespace std;

int main() {
const int &const_ref = 97;
//error! int &const_ref = 97;
cout << "const_ref = " << const_ref << endl;
int j = 100;
int &nonconst_ref = j;
cout << "const_ref = " << nonconst_ref << endl;
system("pause");
return 0;

}


<<C++ primer>>中的那个例子:
const int ival = 1024;
// ok: this is accepted
const int *const &pi_ref = &ival

之所以要在'*'后面加一个const,是因为,&ival表达式得到的是一个const pointer to const int;
如果不加const 也是正确的话那么下面这句也是正确的:
pi_ref++;
而pi_ref++相当于:(&ival)++,假设&ival == 0x12345678,
也相当于(0x12345678)++,当然不正确.
* 号左边的const表示指针指向的对象不能改变,*号右边的const 表示指针本身的值不能改变,
这里就是说:&ival不能改变,&ival是一个右值,不是一个变量,没有分配存储空间所以
以(&ivall)++是错误的.

另外:
const int &const_ref = 97;
相当于:(编译器的行为:)
int tmp = 97;
const int &const_ref = tmp;
加载更多回复(31)

64,652

社区成员

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

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