C++11 新标准(四)

来源:互联网 发布:淘宝上聚划算的要求 编辑:程序博客网 时间:2024/05/17 22:40

1.字符串字面值

(1)标准C++提供的两种字符串:
包含有双引号,产生以空字符结尾的const char数组
有着前标L,产生以空字符结尾的w_const char数组
(2)为了加强C++对Unicode的支持,C++提供三种Unicode编码方式:UTF-8,UTF-16,UTF-32,并新增两种新的字符类别:char16_t,char32_t
u8"This is a UTF-8 string."u"This is a UTF-16 string."U"This is a UTF-32 string."
(3)当创建Unicode字符串字面值时,可以直接在字符串内插入Unicode codepoints。C++11提供了以下的语法:
u8"This is a Unicode Character: \u2018."u"This is a bigger Unicode Character: \u2018."U"This is a Unicode Character: \u2018."
在'\u'之后的是16个比特的十六进制数值;它不需要'0x'的前标。识别字'\u'代表了一个16位的Unicode codepoint;如果要输入32位的codepoint,使用'\U'和32个比特的十六进制数值。只有有效的Unicode codepoints能够被输入。举例而言,codepoints在范围U+D800—U+DFFF之间是被禁止的,它们被保留给UTF-16编码的surrogate pairs。

2.使用或禁用对象的默认函数

(1)在标准C++中,如果用户没有提供,编译器会为对象自动生成默认构造函数,复制构造函数,复制操作符,析构函数,数个全局运算符(operator new和operator delete)
(2)C++11可以使用delete关键字禁止编译器自动产生某些函数
#include <iostream> using namespace std;class Someclass{public:  Someclass() = delete;};int main(){  //[Error] use of deleted function 'Someclass::Someclass()'  Someclass i;  return 0;}
(3)相反地,我们也可以使用default关键字,显式地指明我们希望编译器自动产生这些函数
显式地使用default关键字声明使用类的默认行为,对于编译器来说明显是多余的,但是对于代码的阅读者来说,使用default显式地定义复制操作,则意味着这个复制操作就是一个普通的默认的复制操作。 将默认的操作留给编译器去实现将更加简单,更少的错误发生 ,并且通常会产生更好的目标代码
(4)default关键字可以用在任何的默认函数中,而delete则可以用于修饰任何函数,禁止成员函数以特定的形参调用
struct NoDouble{  void f(int i);  void f(double) = delete;};
若尝试以double形参调用f(),则会发生编译错误
若要彻底禁止以非int的形参调用f(),可以将=delete与模板相结合
struct NoDouble{  void f(int i);  template <typename T> void f(T) = delete;};

2.static_assert

(1)C++11新的关键字static_assert可以解决模板中的状态检察:
static_assert (constant-expression,error-message);
(2)当常数表达式值为false时,编译器会产生相应的错误信息。
下面的例子是前处理器指令#error的替代方案
#include <iostream> using namespace std;//编译时期报错:[Error] static assertion failed: WRONGstatic_assert ( 1 > 2,"WRONG");int main(){  return 0;}
第二个例子会在每个模板类型Check生成时检查assertion。
#include <iostream> using namespace std;template <typename T>struct Check{  static_assert(sizeof(int) <= sizeof(T),"T is not big enough!");};int main(){  //[Error] static assertion failed: T is not big enough!  Check<char> i;  return 0;}
(3)静态assertion在模板之外也是相当有用的。例如,某个算法的实现依赖于long long类别的大小比int还大,这是标准所不保证的。 这种假设在大多数的系统以及编译器上是有效的,但不是全部。

3.sizeof()操作符

C++11允许sizeof操作符用于类型的数据成员上,无需明确的对象
#include <iostream> using namespace std;struct Somestruct{  int num;  char c;};int main(){  Somestruct i;  cout << sizeof(i) << endl;  //标准C++不允许,C++11允许  cout << sizeof(Somestruct::num) << endl;  return 0;}/*输出结果为:84 */

4.tuple元组

(1)在标准库中,tuple(一个N元组:N-tuple)被定义为N个值的有序序列。在这里,N可以是从0到文件中所定义的最大值中的任何一个常数。
特别需要指出的是,tuple中元素是被紧密地存储的(位于连续的内存区域),而不是链式结构。
(2)可以显式地声明tuple的元素类型,也可以通过make_tuple()来推断出元素类型。另外,可以使用get()来通过索引(和C++的数组索引一样,从0而不是从1开始)来访问tuple中的元素
#include <iostream>#include <tuple>using namespace std;int main(){  tuple<int,string,char> t(1,"batman",'i');  int a = get<0>(t);  string b = get<1>(t);  char c = get<2>(t);  cout << a << ' ' << b << ' ' << c << endl;}/*输出结果为:1 batman i */
(3)还有一种方法也可以获取元组的值,通过std::tie解包tuple
int x,y;string a;std::tie(x,a,y) = tp; 
通过tie解包后,tp中三个值会自动赋值给三个变量
解包时,我们如果只想解某个位置的值时,可以用std::ignore占位符来表示不解某个位置的值。比如我们只想解第三个值时:
std::tie(std::ignore,std::ignore,y) = tp; //只解第三个值
(4)swap()函数
swap()既存在成员函数版本也存在非成员函数版本,即a.swap(b)或swap(a,b)均正确
(5)此外,C++11 提供两个表达式用来检查多元组类型的一些特性 (仅在编译期做此检查):
std::tuple_size<T>::value 回传多元组 T 内的元素个数,
std::tuple_element<I, T>::type 回传多元组 T 内的第 I 个元素的类别
template<typename Tuple>void Fun(Tuple& tp){std::tuple_element<0,Tuple>::type first = std::get<0> (mytuple);std::tuple_element<1,Tuple>::type second = std::get<1> (mytuple);}#include <iostream>#include <tuple>#include <typeinfo>int main(){std::tuple<int,char> mytuple(1,'a');std::cout << std::tuple_size<decltype(mytuple)>::value << std::endl;std::tuple_element<0,decltype(mytuple)>::type first = std::get<0> (mytuple);std::tuple_element<1,decltype(mytuple)>::type second = std::get<1> (mytuple);std::cout << first << std::endl << second << std::endl;}/*输出结果为:21a */
(6)遍历tuple
因为tuple的参数是变长的,也没有for_each函数,如果我们想遍历tuple中的每个元素,需要自己写代码实现。比如我要打印tuple中的每个元素:
#include <iostream>#include <tuple>using namespace std;template<class Tuple, std::size_t N>struct TuplePrinter {    static void print(const Tuple& t)    {        TuplePrinter<Tuple, N - 1>::print(t);        std::cout << ", " << std::get<N - 1>(t);    }};template<class Tuple>struct TuplePrinter<Tuple, 1>{    static void print(const Tuple& t)    {        std::cout << std::get<0>(t);    }};template<class... Args>void PrintTuple(const std::tuple<Args...>& t){    std::cout << "(";    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);    std::cout << ")\n";}int main(){tuple<int,char> i(1,'i');PrintTuple(i);return 0; }/*输出结果为:(1, i) */ 
(7)通过tuple_cat连接多个tupe
#include <iostream>#include <tuple>using namespace std;template<class Tuple, std::size_t N>struct TuplePrinter {    static void print(const Tuple& t)    {        TuplePrinter<Tuple, N - 1>::print(t);        std::cout << ", " << std::get<N - 1>(t);    }};template<class Tuple>struct TuplePrinter<Tuple, 1>{    static void print(const Tuple& t)    {        std::cout << std::get<0>(t);    }};template<class... Args>void PrintTuple(const std::tuple<Args...>& t){    std::cout << "(";    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);    std::cout << ")\n";}int main(){std::tuple<int, std::string, float> t1(10, "Test", 3.14);int n = 0;auto t2 = std::tuple_cat(t1, std::make_pair("Foo", "bar"), t1, std::tie(n));n = 10;PrintTuple(t2);n = 11;return 0; }/*输出结果为:(10, Test, 3.14, Foo, bar, 10, Test, 3.14, 10)*/ 

0 0
原创粉丝点击