让我好好想一下
另外,我想问问chinajiji,C++ Primer里面的那段话具体的意思到底是什么呢?
还有,那个special edition的The C++ Programming Language哪里有啊?我现在手上只有3rd Edition的The C++ Programming Language
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].
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:
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:
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;
}
....
};
我有检查了一下,我发现我的观点的确有错误。不过和你举的例子没关系。
引用的确可以指向一个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指向的临时变量并不是常量。