VC10中的C++0x特性 Part 2 (1):右值引用
2009-06-10 20:07:44 来源:WEB开发网问题是这样的,operator+()接受两个参数,一个是 const string&,另一个是 const string& 或 const char * (还有其他重载版本,但在这里我们没有用到),但 operator+() 无法分辨出你塞给它的是 lvalue 还是 rvalue 参数,所以它只好总是创建一个临时 string,并返回这个临时 string。 为什么这跟 vavlue/rvalue 有关系?
当我们要计算 s0 + " " 的值时,很明显这里有必要创建一个新的临时 string。 s0 是一个 lvalue,它已经命名了一个持久对象,因此我们不能修改它。(有人注意到了!) 。如果要计算 (s0 + “ ”) + s1 的值,我们可以简单地将 s1 的内容追加到第一个临时 string 上,而不用创建第二个临时 string 再把第一个丢弃掉。这就是 move 语意背后的核心观念: 因为 s0 + " " 是一个 rvalue ,只有那个在整个程序中唯一能够觉察到临时对象存在的表达式可以引用临时对象。如果我们能检测到表达式是一个非常量 rvalue,我们就可以任意修改临时对象,而不会有人发现。 操作符 +() 本不应该修改它的参数,但如果其参数是非常量 rvalue,谁在乎?照这种方法,每次调用操作符 +() 都把字符追加到唯一的临时对象上,这样就彻底省掉了不必要的动态内存管理和冗余的拷贝操作,呈现出线性复杂度。耶!
从技术上讲,在 C++ 0x 中,每次调用操作符 +() 还是会返回一个单独的临时 string。 然而,第二个临时 string (产生自 (s0 + “ ”) + s1 )可以通过“窃取”第一个临时 string (产生自 s0 + " " )的内存而被构造出来,然后再把 s1 的内容追加到那块内存后面(这将会引发一个普通的重分配操作)。“窃取”是通过指针的操作实现的:第二个临时 string 会先拷贝第一个临时 string 的内部指针,然后再清空这个指针。第一个临时 string 最后被销毁(在分号那地方)时,它的指针已经置为 null 了,因此它的析构函数什么也不会做(译注:也就是说不会释放它的内存,这部分内存现在是第二个临时 string 在使用了)。
更多精彩
赞助商链接