C++11新特性(2)——变量和基本类型
long long
扩展精度浮点数,10位有效数字
nullptr 常量
在新标准下,建议尽量使用新标准nullptr,nullptr是一种特殊类型的字面值,它可以被转换成任意其它的指针类型,虽然其它的方式也是可以的;
auto 类型指示符
- auto让编译器通过初始值来推算变量的类型,所以,其定义的变量必须要有初始值;
- 使用auto也能在一条语句中声明多个变量;因为一条声明语句只能有一个基本数据类型,所以该语句中所有的变量的初始基本数据类型都必须是一样的;
- 使用auto缩写类型,这种写法在其他语言里也有,个人觉得蛮好用的
string str("hello world");
for (auto c : str) {
cout << c;
}
容器的emplace成员
当调用 push 或 insert 成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器里面,但是,当我们调用一个 emplace 成员函数时,则是将函数传递给元素类型的构造函数,会使用这些参数在容器管理的内存中直接构造元素;包括三个函数:emplace_front,emplace,emplace_back,分别对应着 push_front,insert,push_back 为头部,指定位置,尾部;
class MyClass
{
public:
MyClass(int d) : data(d){}
inline int getData() {return data;}
private:
int data;
};
int main() {
vector<MyClass> mys;
mys.emplace_back(10);
mys.push_back(MyClass(20));
for (auto itr = mys.begin(); itr != mys.end(); itr++) {
cout << (*itr).getData() << endl;
}
return 0;
}
右值引用
右值引用就是必须绑定到右值的引用,通过 && 来获得右值引用;
左值和右值
- 左值:在赋值号左边,可以被赋值的值,可以取地址;
- 右值:在赋值号右边,取出值赋给其他变量的值;
- 当一个对象被用作右值的时候,用的是对象的值(内容);
- 当对象被用作左值的时候,用的是对象的身份(在内存中的位置);
int a = 10; // a和b是左值
int b = a; // 10是右值,字符串不是右值
引用
在平时编码的过程中为了减少数据的拷贝,提高性能,一般通过引用的方式来传递参数
- 左值引用:type & 引用名 = 左值表达式
- 右值引用:type && 引用名 = 右值表达式
int main() {
int i = 1; //i为常规左值
int &r = i; //正确:r绑定到i上,r是一个引用
int &&rr = i; //错误:不能将一个右值引用绑定到左值i上
int &r2 = i * 1; //错误:等号右边是一个右值,但左值引用只能绑定到左值上
int &&rr2 = i * 1; //正确:右值引用绑定到右值上
const int &r3 = i * 1; //正确:可以将一个const的左值引用绑定到右值上
return 0;
}
移动构造(move)
- 对于拷贝构造函数而言,形参是一个左值引用,而不能是某些函数临时返回的函数对象,而且拷贝构造函数往往是深拷贝,一般不会破环实参对象
- 移动构造函数接受的是一个右值,其核心思想是通过转移实参对象的数据以达成构造目的对象的目的;也就是说,移动构造函数会修改实参对象,一般来说调用了移动构造函数之后,实参对象的线管变量资源就会被转移,原本实参的变量就会被置空,也就是实参就不能再使用了
A a("hello");
A b=std::move(a);
A c=static_cast<A&&>(b);
class A{
public:
A(string s): name(new string(s)){
cout<<"构造函数“<<endl;
}
A(const A&s): name(new string(*a.name)){
cout<<"拷贝构造函数”<<endl;
}
A (A&&a){
name = a.name;
a.name = nuulptr;
cout<<"移动构造函数"<<endl;
}
}