1. C++11简介
2. 列表初始化
3. 变量类型推导
4. 范围for循环
5. 新增加容器---静态数组array、forward_list以及unordered系列
6. 默认成员函数控
7.左值引用VS右值引用
在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于TC1主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率。
int array1[] = {1,2,3,4,5};
int array2[5] = {0};
vectornums{1,2,3,4};
#include
#include
#include
#include
template
T1 Add(const T1& left, const T2& right)
{
return left + right;
}
int main()
{
int a = 10;
int b = 20;
// 用decltype推演a+b的实际类型,作为定义c的类型
decltype(a+b) c;
cout<
void* GetMemory(size_t size)
{
return malloc(size);
}
int main()
{
// 如果没有带参数,推导函数的类型
cout << typeid(decltype(GetMemory)).name() << endl;
// 如果带参数列表,推导的是函数返回值的类型,注意:此处只是推演,不会执行函数
cout << typeid(decltype(GetMemory(0))).name() <
int main()
{
int x = 10;
//typeid(x)y1 = 5;//error
// typeid拿到只是类型的字符串,不能用这个再去定义对象什么的
decltype(x) y1 = 20;
cout << typeid(y1).name() <<" y1:" << y1 << endl;//int
auto y2 = 3.14;
cout << typeid(y2).name()<<" y2:"<
运行结果:
上面我们提到了用迭代器遍历其实挺麻烦的,我们有更直接的方法--范围for
这个代码想来有的小伙伴页见过,作用是统计数组中数字的个数
#include
#include
using std::vector;
using std::unordered_map;
int main()
{
unordered_map count;
vectornums{ 1,1,2,2,2,3,4,4,4,4,5 };
for (auto num : nums)
{
count[num]++;
}
for (auto e : count)
cout << e.first << "出现了 "<
实际上范围for的底层是封装了迭代器的。
array官方文档 : cplusplus.com/reference/array/
新增的array主要是为了替代C语言中的静态数组
//C++11新增的array容器测试
int main()
{
const size_t N = 100;
int a1[N];
// C语言数组越界检查,越界读基本检查不出来,越界写是抽查
a1[N];
//a1[N] = 1;
a1[N+5] = 1;
// 越界读写都可以被检查出来
// 实际情况:array用得很少,一方面大家用c数组用惯了
// 用array不如用vector + resize去替代c数组
array a2;
a2[N];
a2[N] = 1;
a2[N + 5] = 1;
return 0;
}
//模拟实现的string, 方便观察现象
namespace hy
{
class string
{
public:
typedef char* iterator;
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
string(const char* str = "")
:_size(strlen(str))
, _capacity(_size)
{
_str = new char[_capacity + 1];
strcpy(_str, str);
}
void swap(string& s)
{
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
// 拷贝构造
string(const string& s)
:_str(nullptr)
{
cout << "string(const string& s) -- 拷贝构造(深拷贝)" << endl;
//string tmp(s._str);
//swap(s);
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}
// 移动构造
string(string&& s)
:_str(nullptr)
, _size(0)
, _capacity(0)
{
cout << "string(string&& s) -- 资源转移" << endl;
swap(s);
}
// 拷贝赋值
string& operator=(const string& s)
{
cout << "string& operator=(string s) -- 拷贝赋值(深拷贝)" << endl;
string tmp(s);
swap(tmp);
return *this;
}
// 移动赋值
string& operator=(string&& s)
{
cout << "string& operator=(string s) -- 移动赋值(资源移动)" << endl;
swap(s);
return *this;
}
~string()
{
delete[] _str;
_str = nullptr;
}
char& operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
void reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
void push_back(char ch)
{
if (_size >= _capacity)
{
size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
reserve(newcapacity);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
const char* c_str() const
{
return _str;
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
}
hy::string to_string(int value)
{
bool flag = true;
if (value < 0)
{
flag = false;
value = 0 - value;
}
hy::string str;
while (value > 0)
{
int x = value % 10;
value /= 10;
str += ('0' + x);
}
if (flag == false)
{
str += '-';
}
std::reverse(str.begin(), str.end());
return str;
}
// 拷贝构造和移动构造
int main()
{
hy::string ret = to_string(-3456);
hy::string s1("1111111");
hy::string s2(s1);
return 0;
}
int main()
{
hy::string str1("hello");
hy::string str2(str1); // 拷贝构造
hy::string str3(std::move(str1)); // 移动构造
std::string s1("hello world");
std::string s2(s1); // 拷贝构造
// std::string s3(s1+s2);
std::string s3 = s1 + s2; // 移动构造
std::string s4 = move(s1);
return 0;
}
int main()
{
std::vector v;
hy::string s1("hello");
v.push_back(s1);
cout << "----------------------------------" << endl;
v.push_back(hy::string("world"));
//v.push_back("world");
cout << "===================================" << endl;
std::list lt;
//bit::string s1("hello");
lt.push_back(s1);
cout << "----------------------------------" << endl;
lt.push_back(hy::string("world"));
//lt.push_back("world");
return 0;
}
class Person
{
public:
Person(const char* name = "", int age = 0)
:_name(name)
, _age(age)
{}
// 会默认生成拷贝构造+移动构造
// 不想让Person对象拷贝
//Person(const Person& p) = delete;
/*~Person()
{}*/
private:
hy::string _name;
int _age;
};
int main()
{
Person s1("张三", 7);
Person s2 = s1; // 拷贝构造
Person s3 = std::move(s1); // 移动构造 (没有移动构造,再调用拷贝构造)
//Person s4;
//s4 = std::move(s2);
return 0;
}
int main()
{
//左值:可以取地址的值-->内存中有位这个变量开辟空间
/*int a = 20;
const int b = 5;
int* p = &a;
*p = 100;
//a,b,p都是左值*/
//以下的p、b、c、*p都是左值
int* p = new int(0);
int b = 1;
const int c = 2;
// 以下几个是对上面左值的左值引用
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;
//右值:不能取地址
double x = 1.1, y = 2.2;
10;
x + y;
fmin(x, y);
//cout << &10 << endl;
//cout << &(x + y) << endl;
// 以下几个都是对右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);
return 0;
}
void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// 万能引用:t既能引用左值,也能引用右值
// 引用折叠
template
void PerfectForward(T&& t)
{
// 完美转发:保持t引用对象属性
Fun(std::forward(t));
}
#include"list.h"
int main()
{
PerfectForward(10); // 右值
int a;
PerfectForward(a); // 左值
PerfectForward(std::move(a)); // 右值
const int b = 8;
PerfectForward(b); // const 左值
PerfectForward(std::move(b)); // const 右值
hy::list lt;
hy::string s1("hello");
lt.push_back(s1);
cout << "----------------------------------" << endl;
//lt.push_back(bit::string("world"));
lt.push_back("world");
return 0;
}
问题:
左值引用可以引用右值吗? 右值引用可以引用左值吗?
示例2:
//有条件的支持
// 左值引用可以引用右值吗? const的左值引用可以
//double& r1 = x + y; //error
const double& r1 = x + y;//有条件的
// 右值引用可以引用左值吗?可以引用move以后的左值
//int&& rr5 = b;
int&& rr5 = move(b);
结论1 :const修饰的左值可以引用右值,因为本身不可修改,因而产生了万能引用
//万能引用
// x既能接收左值,也能接收右值
template
void Func(const T& x)
{}
结论2 : 右值不能引用左值,但是可以引用move后的左值,使用move有一定风险,要小心使用。
int main()
{
double x = 1.1, y = 2.2;
int&& rr1 = 10;
const double&& rr2 = x + y;
rr1 = 20;
//rr2 = 5.5;//error
cout << rr1 << " " << rr2 << endl;
return 0;
}
//实现一个只能在对上创建对象的类
class HeapOnly
{
public:
HeapOnly()
{
_str = new char[10];
}
~HeapOnly() = delete;
void Destory()
{
delete[] _str;
operator delete(this);
}
private:
char* _str;
//...
};
//使用
int main()
{
//HeapOnly hp1;
//static HeapOnly hp2;
HeapOnly* ptr = new HeapOnly;
//delete ptr;
ptr->Destroy();
//operator delete(ptr);
return 0;
}