C++11及其新特性 (一)
1、explicit 关键字
明确的;清楚的;直率的;详述的
explicit
作用是表名该构造函数是显示的
,而非隐式的,不能进行隐式转换!跟它相对应的另一个关键字是implicit,意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式)
。
#include <iostream>
#include <string>
using namespace std;
class student {
public:
explicit student(int _age) {
age = _age;
cout << "age = " << age << endl;
}
student(int _age, const string _name) {
age = _age;
name = _name;
cout << "age = " << age << "; name = " << name << endl;
}
~student() {
}
int getAge() {
return age;
}
string getName() {
return name;
}
private:
int age;
string name;
};
int main(void) {
student xiaoM(18);//显示构造
student xiaoW(19, "小花");//显示构造
//student xiaoL = 18; //隐式构造 因为加上了 关键字 explicit,所以不能进行隐式构造
student xiaoMei = {18, "小美"};//隐式构造 初始化参数列表, C++11前编译不能通过,C++11新增特性
system("pause");
return 0;
}
2、左值和右值
存储的层次结构
访问速度超快 访问速度快 访问速度慢
容量非常小 容量一般 容量巨大
按字面意思,通俗地说,以赋值符号 = 为界, = 左边地就是左值(
lvalue
),= 右边就是右值(rvalue
)
lvalue
- 代表一个在内存
中占有确定位置的对象(换句话说就是有一个地址)。rvalue
- 通过排他性来定义,每个表达式不是lvalue
就是rvalue
。- 因此从上面的
lvalue
的定义,rvalue
是在不在内存中占有确定位置的表达式,而是存在在寄存器
中。
3、函数返回值当引用
C++引用使用时的难点:
- 当函数返回值为引用时
- 若返回栈变量,不能成为其引用的初始值,不能作为左值使用
- 若返回静态变量或全局变量
- 可以成为静态变量或全局变量
- 即可作为右值使用,也可作为左值使用
- 返回形参当引用
- C++链式编程中,经常用到引用,运算符重载专题
ostream&
)
- C++链式编程中,经常用到引用,运算符重载专题
test.cpp
#include <iostream>
using namespace std;
int &demo(int **addr) {
int i = 666;
*addr = &i;
printf("i 的地址: %p, i = %d", &i, i);
return i;
}
int& demo_static(int** addr) {
static int i = 666;
*addr = &i;
printf("i 的地址: %p, i = %d", &i, i);
return i;
}
//第三种情况, 函数返回形参当引用 和 局部变量一样
int& demo3(int var) {
var = 666;
return var;
}
int demo1() {
int i = 0;
return 0;
}
int main(void) {
int* addr = NULL;
int ret = demo(&addr);// 赋值是可以的
/*
第一种情况,函数返回局部变量引用不能成为其他引用的初始值
int& i = demo(&addr);
printf("addr 的地址: %p, i = %d", addr, i);
i = 888;
cout << "-----------------" << endl;
demo(&addr);
//输出 i = 666,即使在上面我们进行了 i = 888操作,但i使用的地址在demo中被修改了
printf("addr 的地址: %p, i = %d", addr, i);
*/
/*第二种情况,函数返回局部变量不能作为左值
demo(&addr) = 888;
printf("addr: %p, value:%d\n", addr, *addr);//addr的地址其实就是 栈顶地址,
demo1(); //调用demo1() 栈顶地址的数据被修改
printf("addr: %p, value:%d\n", addr, *addr);
addr: 000000B5F5FDF934, value : 888
addr : 000000B5F5FDF934, value : 0
*/
/*第三种情况,返回静态变量 可作为右值使用,也可作为左值使用
demo_static(&addr) = 888;
printf("addr: %p, value:%d\n", addr, *addr);
demo1();
printf("addr: %p, value:%d\n", addr, *addr);
addr: 00007FF797A54004, value : 888
addr : 00007FF797A54004, value : 888
*/
return 0;
}
4、新增容器-array
-
array 容器是
C++11
标准中新增的序列容器,简单地理解,它就是在 C++ 普通数组的基础上,添加了一些成员函数和全局函数。 -
array是将元素置于一个
固定数组中加以管理
的容器
。 -
array可以随机存取元素,支持索引值直接存取, 用[]操作符或at()方法对元素进行操作,也可以使用迭代器访问
-
不支持
动态的新增删除操作 -
array可以
完全替代C语言中的数组
,使操作数组元素更加安全! -
#include
-
array_test.cpp
-
#define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING #include <array> #include <iostream> using namespace std; class student { public: student() { age_ = 0; }; private: int age_; }; int main(void) { //array的定义 //array<T,int> arrT;//T 代表存储类型, int是开辟数组地大小 array<int, 10> a1; array<student, 3> stuArr; //array的赋值 a1.assign(666);//将所有元素赋值为666 for (unsigned int i = 0; i < a1.size(); i++) { cout << a1[i] << ' '; } cout << endl; a1.fill(888);//比assign安全 for (unsigned int i = 0; i < a1.size(); i++) { cout << a1[i] << ' '; //888 888 ... 888 } cout << endl; array<int, 4> ax = { 1,2,3 };//可少不可多 array<int, 4> ay; ay = { 1,2,3,6 }; ax = ay;//类型相同的可以进行赋值 ay.swap(ax);//交换array中的值 //array的大小 ax.size();//返回容器元素的个数 ax.empty();//永远为非空 //array的数据存取 a1[2] = 34; a1.at(3) = 44; a1.front() = 250;//接口返回引用 a1.back() = 1314; for (unsigned int i = 0; i < a1.size(); i++) { cout << a1[i] << ' '; } //250 888 34 44 888 888 888 888 888 1314 cout << endl; //迭代器:begin(),end(),倒序rbegin(),rend() //常量迭代器 cbegin(),cend(),crbegin(),crend() array<int, 5> arrayInt = { 1,2,3,4,5 }; //使用普通迭代器输出 for (array<int, 5>::iterator it = arrayInt.begin(); it != arrayInt.end(); it++) { cout << *it << " "; *it = -1;//允许修改 } cout << endl; //使用常量迭代器输出 for (array<int, 5>::const_iterator it = arrayInt.cbegin(); it != arrayInt.cend(); it++) { cout << *it << " "; //-1 -1 -1 -1 -1 //*it = 1;//不允许修改 } cout << endl; return 0; }
-