如何让C++0x右值引用发挥威力?
右值引用号称将解决C++的临时对象问题,上代码:
- C/C++ code
// 程序一,VC10,此时如何通过右值引用,解决重新new内存的问题?
// 由于MinGW 4.4使用引用计数,所以无法对比
#include <stdio.h>
#include <string>
std::string test(const std::string& str)
{
printf("1: 0x%08x\n", str.c_str());
std::string tmp(str);
printf("2: 0x%08x\n", tmp.c_str());
return std::move(tmp);
}
int main()
{
printf("3: 0x%08x\n", test("右值引用测试!").c_str());
return 0;
}
输出:
1: 0x0012ff40
2: 0x0012fedc
3: 0x0012ff24
如何做到第2次与第3次的内存地址一样?
- C/C++ code
// 程序二,难道VC和GCC,对vector都使用了引用计数?// MinGW 4.4也是一样的结果#include <stdio.h>#include <vector>std::vector<int> test(const std::vector<int>& v){ printf("1: 0x%x\n", &v[0]); std::vector<int> t(v); t.push_back(88); printf("2: 0x%x\n", &t[0]); return t; // 与std::move(t);结果一样,为啥? //return std::move(t);}int main(){ std::vector<int> v(1000); // 改变这个值的大小,将会看到v2[0]地址的变化,为啥? v.push_back(2); v.push_back(5); v.push_back(9); std::vector<int> v2 = test(v); printf("3: 0x%x\n", &v2[0]); for (int i = 0; i < 100; ++i) v2.push_back(i); printf("4: 0x%x\n", &v2[0]); return 0;}
输出:
1: 0x4be880
2: 0x4c0088
3: 0x4c0088
4: 0x4c0088
为什么2、3、4的结果一样,都受main里的v的初始化大小的影响?
难道vector自己实现了类似右值引用这样的功能?
目前我能确定的是:VC的std::string从VC7开始,就不再使用引用计数;而MinGW(GCC)的std::string一直在使用引用计数。
是否右值引用的功能,需要库的支持:通过&&拷贝构造?
类似于:
- C/C++ code
string(string&& s) { ... }
才能发挥威力?
[解决办法]
因为nrv等返回值优化规则。
[解决办法]
深度,关注!
[解决办法]
nrvo是有限的.
[解决办法]
程序员杂志专门有篇介绍这个
[解决办法]
[解决办法]
gcc中,string有引用计数。
除此之外,所有的函数返回确定对象,都不生产临时对象,比如:
class T;
T create_T(...){
T x;
return x;
}
要想产生临时对象,要这样做:
T create_T(...){
if( ...){
T t1;
return t1;
}else{
T t2;
return t2;
}
}
[解决办法]
珍惜生命,远离c++0x
右值引用是一种新的类型,当然需要新的函数来配合了。
[解决办法]
而且右值引用并没有什么值得大题小作的。
gcc很久以前就注意这个问题了。
对于:
T createT();
T t = createT();
会调用3次构造函数(其中2次是拷贝),2次析构函数。
一次是createT()函数内那个局部变量, 出函数后析构了。
一次是函数返回值那个临时变量,赋值后析构了。
一个是最外面那个t。
如果用了右值引用, 也就是临时变量为右值引用,这时2次构造函数(一次右值拷贝),1次析构函数。
很郁闷的是,那个右值拷贝构造函数,没有默认的,必须手动提供一个(这点我弄得我很郁闷)。
而gcc的优化,是1次构造函数,无析构函数。
其中string的实现是最复杂的,利用了类似“写时复制”的技术。
------解决方案--------------------
若是我的KYString, c_str()方法要保证引用计数只能为1,所以需要重新分配缓冲区;若想都一样地址可以使用(char*)转换即可。
KYString类声明如下:
- C/C++ code
#include<iostream>#include<algorithm>#include<vector>#include<string>using namespace std;void print(int x){cout<<x<<' ';}int main(){ vector<int> iter1,iter2; for(int i=1;i<100;i++) { if(i%2==0) iter1.push_back(i); else iter2.push_back(i); } for_each(iter1.begin(),iter1.end(),print); cout<<endl; for_each(iter2.begin(),iter2.end(),print); cout<<endl;}