IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++标准11-14新特性总结 -> 正文阅读

[C++知识库]C++标准11-14新特性总结

  • 1. 演进、环境与资源
    • 版本:c++98(1.0),c++04,c++11(2.0),c++14
  • 2. Variadic Template(可变参数模板)(重点,也是难点)
    • ...就是pack(包),表示任意个数、任意类型的参数
    • template parameters pack:模板参数包
    • function parameter types pack:函数参数类型包
    • function parameter pack:函数参数包
    • 模板有特化的概念。重载中,函数谁会更特别,则调用更特化的。
    • 代码:
      • #include<iostream>
        using namespace std;
        namespace variadic{
        	void print(){
        	}
        	
        	template <typename T, typename... Types>
        	void print(const T& firstArg, const Types&... args){
        		cout << sizeof...(args) << " " << firstArg << endl;
        		print(args...);
        	}
        	template<typename... Values> class tuple;
        	template<> class tuple<> {};
        	template<typename Head, typename... Tail>
        	class tuple<Head, Tail...>: private tuple<Tail...>{
        		typedef tuple<Tail...> inherited;
        		public:
        			tuple() {}
        			tuple(Head v, Tail... vtail): m_head(v), inherited(vtail...) {}
        			
        			Head head() {return m_head;}
        			inherited& tail() { return *this; }
        		protected:
        			Head m_head;
        	};
        	
        	
        }
        using namespace variadic;  // 如果不加这一行,编译不通过 
        int main(){
        	int a = 1;
        	char c = 'T';
        	int b[10] = {0};
        	string s("abs");
        //	cout << b << endl;  //打印的是地址 
        //	s = "dsd";  // 可以通过编译
        	print(a, c, b, s); 
        
        //	tuple<int, float, string> t(41, 6.3, "nico");
        //	cout << t.head() << endl;
        //	cout << t.tail().head() << endl;
        	return 0;
        }

  • 3. Spaces in Template Expression、nullptr、auto
    • Spaces in Template Expression
      • vector<vector<int> > v; 可以写成 vector<vector<int> > v;(中间的空格可以不写
    • nullptr
      • C++11开始,定义了空指针的常值为nullptr
    • auto
      • auto可以自动推导变量的类型,当类型比较长、或者复杂的表达式 lambda,可以使用auto代替。
  • 4. Unifrom Initialzation一致性初始化
    • 需要注意的是,initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。并且,拷贝或赋值一个initializer_list对象不会拷贝列表中的元素,其实只是引用而已,原始列表和副本共享元素,本质是由于这是一种浅拷贝,二者底层上只是把一个指针同时指向一个地址。
    • 现在有了initializer_list<>,所有容器都接受指定类型任意数量的值用于构建或赋值等(类型要一致,{}不会进行类型转换)。
    • 代码:
      • vector<int> v {1, 2, 3, 4};
  • 5. Initialzer_list
    • std::initializer_list有三个成员接口:size(), begin(), end();
  • 6. Explicit for ctors taking more than one argument带多个参数的系数的显式
    • 加入了explicit, 必须显式调用构造函数。不允许进行隐式的调用构造函数。
    • 代码:
      • #include<iostream>
        struct Complex{
        	double _real;
        	double _i;
        //	explicit  // 加入了explicit, 必须显式调用构造函数 
        	Complex(double real, double i = 0) : _real(real), _i(i) {}
        	Complex operator + (const Complex &c){
        		return Complex(c._real + _real, c._i + _i);
        	}
        	~Complex() = default;
        };
        int main() {
        	Complex c1(4, 2);
        	Complex c2 = c1 + 5; // 编译器会隐式地调用构造函数来构造一个Complex(5)
        	return 0;
        }
        

  • 7. Range - based for statement
    • 代码:
      • vector<int> v {1,2, 3,4};
      • for (auto a : v)
        • cout << a << endl;
  • 8. =default. =delete(https://blog.csdn.net/baidu_17611285/article/details/80505902)
    • big-five:默认的构造函数,默认的拷贝构造函数,默认的赋值构造函数,移动构造函数,移动赋值构造函数
    • default就是专门作用于以上的big-five,表示当我们已经定义了专门的构造、拷贝构造、赋值构造、移动构造等等函数,此时编译器就不会自动加上big-five,但假如此时还希望用这些默认的函数,可加上=default来实现,如下图。而“=delete”表示的是我们不想要这个函数,若去调用加了“=delete”的函数,则编译报错。另外,“=delete“可加在任意函数,不局限于类的成员函数。default还能用于析构函数身上,但很少用到。
    • =default(也可以使用在析构函数上)
      • 在标准库中,default都是用于big-five的函数。
    • =delete
    • 一个类只要带着指针成员,几乎就断定需要我们自己去写出那些Big-Three(构造,拷贝构造,赋值构造,C++11就是Big-FIve);反之,如果不带指针成员,几乎就不需要自己去实现Big-Three,一般编译器默认的就够了。因为,编译器的默认拷贝是浅拷贝,带指针的就只拷贝指针本身,一般我们需要深拷贝,也就是指针所指的那块内存要重新分配,再拷贝指针。
    • 代码:
    • ?
      #include<iostream>
      using namespace std;
      class Zoo{
      	private:
      		int d1, d2;
      	public:
      		Zoo(int i1, int i2):d1(i1), d2(i2) {}
      		// 由于写了构造函数,系统不会自动在生成构造函数。
      		// 故如果不写下面这一行,Zoo z1;将会报错。 
      		Zoo() = default;   
      		Zoo(const Zoo&) = delete;
      		Zoo(Zoo &&) = default;
      		Zoo& operator = (const Zoo&) = default;
      		Zoo& operator = (const Zoo&&) = delete;
      		virtual ~Zoo() {}
      }; 
      
      int main() {
      	Zoo z1;
      //	Zoo z2(z1);   //  由于使用了Zoo(const Zoo&) = delete;,故这一行报错 
      	return 0;
      }

  • 9. Alias Template(模板别名)(8.Alias Template(模板别名)_baidu_17611285的博客-CSDN博客_alias template
    • using这种方法类似于C++中的typedef,但这种C++11的新机制不仅仅是为了通过设置模板别名来少写几个字,且其也无法通过typedef或#define代替
    • 代码:
    • #include<iostream>
      #include<vector>
      using namespace std;
      //  template要放在函数外面 
      // 使用typedef语法复制等 
      template<typename T>
      using Vec = vector<T, allocator<T>>;
      
      template <typename T, template <class> class Container>
      class XCLs {
      	private:
      		Container<T> c;
      	public:
      		XCLs() {
      			for(long i = 0; i < 10; i++)
      				c.insert(c.end(), T()); 
      				
      //			output_static_data(T());
      			Container<T> c1(c);
      			// std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝所以可以提高利用效率,改善性能.。
      			Container<T> c2(std::move(c));
      			c1.swap(c2);
      		}
      };
      int main() {
      	XCLs<int, Vec> c1;
      	return 0;
      }

  • 10.Template template parameter
  • 11. Type Alias, noexception, override, final(C++新特性之Type Alias、noexcept、override、final_u013635579的博客-CSDN博客
    • Type Alias类型别名
      • 代码:
        • class Base {};
        • using A = Base;
    • noexception
      • noexcept来指定某个函数不会抛出异常
    • override
      • 在C++11中提供的override关键字可以解决这一问题,它标记派生类中的虚函数,如果基类中的虚函数没有被覆盖,编译器则报错
    • final
      • final新增两种功能:(1)、禁止基类被继承,(2)、禁止虚函数被重写;
  • 12. decltype
    • decltype(表达式),返回表达式(可以使函数)的类型。
    • dectype并不会执行表达式,只是推出类型,而auto会执行。
  • 13. lambdas(C++之Lambda表达式 - 季末的天堂 - 博客园
    • lamdba函数是inline函数。
    • [函数对象参数] (操作符重载函数参数) mutable 或 exception 声明 -> 返回值类型 {函数体}
    • C++ 11 中的 Lambda 表达式用于定义并创建匿名的函数对象,以简化编程工作。
    • 空。没有任何函数对象参数。
    • =。函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是值传递方式(相
    • 当于编译器自动为我们按值传递了所有局部变量)。
    • &。函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是引用传递方式
    • (相当于是编译器自动为我们按引用传递了所有局部变量)。
    • this。函数体内可以使用 Lambda 所在类中的成员变量。
    • a。将 a 按值进行传递。按值进行传递时,函数体内不能修改传递进来的 a 的拷贝,因为默认情况下函数是 const 的,要
    • 修改传递进来的拷贝,可以添加 mutable 修饰符。
    • &a。将 a 按引用进行传递。
    • a,&b。将 a 按值传递,b 按引用进行传递。
    • =,&a,&b。除 a 和 b 按引用进行传递外,其他参数都按值进行传递。
    • &,a,b。除 a 和 b 按值进行传递外,其他参数都按引用进行传递。
  • 14. Rvalue reference and Move Semantics
    • lvalue(locator value)代表一个在内存中占有确定位置的对象(换句话说就是有一个地址)。
    • rvalue通过排他性来定义,每个表达式不是lvalue就是rvalue。因此从上面的lvalue的定义,rvalue是不在内存中占有确定位置的表达式。
    • 举例:理解C和C++中的左值和右值_xuwqiang1994的博客-CSDN博客
      • 常量4和表达式var+1都不是lvalue(它们是rvalue)。它们不是lvalue,因为都是表达式的临时结果,没有确定的内存空间(换句话说,它们只是计算的周期驻留在临时的寄存器中)。因此给它们赋值没有语意-这里没有地方给它们赋值。
      • foo返回一个临时的rvalue。尝试给它赋值,foo()=2,是一个错误;编译器期待在赋值运算符的左部分看到一个lvalue。
      • 不是所有的对函数调用结果赋值都是无效的。比如,C++的引用(reference)让这成为可能:
      • const int a = 10; //‘a’是一个左值
      • a = 10; //但是它不能被赋值
      • […] 一个左值没有数组类型,没有不完全类型,没有const修饰的类型,并且如果它是结构体或联合体,则没有任何const修饰的成员(包含,递归包含,任何成员元素的集合)。
      • 一个非函数,非数组类型的左值T可以被转换成一个右值。[…]如果T是一个非类类型,那么转换成的右值类型是T的非CV修饰版本。否则,那个右值类型是T。
      • && 语法是新的右值引用。的确如它名字一样-给我们一个右值的引用,在调用之后将被析构。我们可以使用我们只是“偷”这个内部的右值这个事实-我们根本不需要它们!输出为:
    • 代码:
    • #include<iostream>
      using namespace std;
      
      class Intvec
      {
      public:
          explicit Intvec(size_t num = 0)
              : m_size(num), m_data(new int[m_size])
          {
              log("constructor");
          }
      
          ~Intvec()
          {
              log("destructor");
              if (m_data) {
                  delete[] m_data;
                  m_data = 0;
              }
          }
      
          Intvec(const Intvec& other)
              : m_size(other.m_size), m_data(new int[m_size])
          {
              log("copy constructor");
              for (size_t i = 0; i < m_size; ++i)
                  m_data[i] = other.m_data[i];
          }
      
      //    Intvec& operator=(const Intvec&& other)  // 执行v2 = v1;会报错 
          Intvec& operator=(const Intvec& other)
          {
              log("copy assignment operator");
              Intvec tmp(other);  // 函数执行完后, tmp会被释放掉 
              // other中的内容还在
              std::swap(m_size, tmp.m_size);   //由于other是常量类型,故不能调用std::swap(m_size, other.m_size);
              std::swap(m_data, tmp.m_data);
              return *this;
          }
          
          Intvec& operator=(Intvec&& other) // 将&&理解成偷 
      	{
      	    log("move assignment operator");
      	    std::swap(m_size, other.m_size);
      	    std::swap(m_data, other.m_data);
      	    return *this;
      	}
      private:
          void log(const char* msg)
          {
              cout << "[" << this << "] " << msg << "\n";
          }
      
          size_t m_size;
          int* m_data;
      };
      int main() {
      	Intvec v1(20);
      	Intvec v2;
      	
      	cout << "assigning lvalue...\n";
      //	v2 = v1;
      	//  Intvec(33)构建了一个临时对象,执行完下面这一条语句,会被释放。 
      	// Intvec& operator=(const Intvec& other), 里面要是const类型,不然如果不在写一个=重载函数,系统会说找不到=重载函数 
      	//	或者写成 Intvec& operator=(Intvec&& other)  
      	v2 = Intvec(33);    //系统调用的是Intvec& operator=(Intvec&& other)  
      	
      	cout << "ended assigning lvalue...\n";
      	return 0;
      }

  • 15. Perfect Forwarding(完美传递)
    • 顾名思义,完美转发是将参数不改变属性的条件下,转发给下一个函数. 因为普通函数的参数一旦具名,始终都是lvalue. 如果把rvalue转发到下一个函数上的参数中,还是rvalue(不会产生过多的内存)这就是完美转发的目的。
  • 16. Move-aware class
  • 17. Vector
    • vector里面只能包含对象,不能放引用类型。
    • 引用不是对象。
  • 18. Hashtable, Hast funciton
    • Hast funciton(系统会有一个计算hashcode的函数)
  • 19. Tuple
    • 元编程对类型进行操作。
    • 参看2. Variadic Template代码。
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-30 11:45:05  更:2021-09-30 11:46:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:28:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码