The C++ Programming Language Chapter 3 ( 读书笔记)

来源:互联网 发布:网络信息群发软件 编辑:程序博客网 时间:2024/06/04 19:10

Chapter 3 New Language Features

The New Language Features

nullptr and std::nullptr_t

nullptr : C++11定义的空指针类型; 在C中空指针类型NULL 的值为(void*)0, 而在原C++中NULL 的值为0, 即

  #ifdef __cplusplus  #define NULL 0  #else  #define NULL (void*)0  #endif

当以前使用NULL时, 会出现歧义,或者调用不符合预期的情况, 而nullptr能比较好的解决这个问题。

void f(int);void f(void*);f(0); //call f(int)f(NULL); //call f(int) if NULL is 0, ambiguousf(nullptr); //call f(void*) 

std::nullptr_t: 在< cstddef> 中定义:

namespace std{  typedef decltype(nullptr) nullptr_t;}

auto

根据右边所提供值的类型,来确定所定义的变量类型(右边必须提供值)

auto i; //errorauto i  = 10; // i is int

Uniform Initialization and Initializer Lists

即:

//用法int values[] { 1, 2, 3 };std::vector<int> v { 2, 3, 5, 7, 11, 13, 17 };std::vector<std::string> cities {"Berlin", "New York", "London", "Braunschweig", "Cairo", "Cologne"};std::complex<double> c{4.0,3.0}; // equivalent to c(4.0,3.0)//初始化为类型的初始值int i; // i has undefined valueint j{}; // j is initialized by 0int* p; // p has undefined valueint* q{}; // q is initialized by nullptr

当初始化列表中的值与定义的类型值不匹配时,所遵循的规则为(大吃小),即所定义的类型的值能否表示初始化列表中的值的类型。如果能,那么就不会产生错误,否则则会出错, 如:

int x1(5.3); // OK, but OUCH: x1 becomes 5int x2 = 5.3; // OK, but OUCH: x2 becomes 5int x3{5.0}; // ERROR: narrowingint x4 = {5.3}; // ERROR: narrowingchar c1{7}; // OK: even though 7 is an int, this is not narrowingchar c2{99999}; // ERROR: narrowing (if 99999 doesn’t fit into a char)std::vector<int> v1 { 1, 2, 4, 5 }; // OKstd::vector<int> v2 { 1, 2.3, 4, 5.6 }; // ERROR: narrowing doubles to ints//class P{public:    P(int,int);    P(std::initializer_list<int>);};P p(77,5); // calls P::P(int,int)P q{77,5}; // calls P::P(initializer_list)

range for

std::vector<string> vs;for(auto str : vs){    std::cout << str << std::endl;}

Move Semantics and Rvalue References(move 语句与右值引用)

用于减少对象拷贝开销。

//move 定义与<utility>, 简单使用X x;coll.insert(x); // inserts copy of x (OK, x is still used)...coll.insert(x+x); // moves (or copies) contents of temporary rvalue...coll.insert(std::move(x)); // moves (or copies) contents of x into coll// = 号与constructor重载class X {public:    X (const X& lvalue); // copy constructor    X (X&& rvalue); // move constructor    ...    X& operator= (const X& lvalue); // copy assignment operator    X& operator= (X&& rvalue); // move assignment operator}//void foo(const X&); //如果没用定义void foo(X&&); 可接受右值引用

Raw String Literals

可用于构造复杂的表达式。

R"nc(a\    b\nc()"    )nc" = "a\\\n b\\nc()\"\n "

Keyword noexcept

使函数不会抛出异常,如果抛出,程序会被 std::terminate()终止。(std::terminate() 里面默认调用std::absort()).

Keyword constexpr

可以在编译期间确定的值。

Variadic Templates

可变参数模板

void print (){}template <typename T, typename... Types>void print (const T& firstArg, const Types&... args){    std::cout << firstArg << std::endl; // print first argument    print(args...); // call print() for remaining arguments}print (7.5, "hello", std::bitset<16>(377), 42);

output:

7.5hello000000010111100142

Alias Templates (Template Typedef)

用法:

template <typename T>using Vec = std::vector<T,MyAlloc<T>>; // standard vector using own allocatorVec<int> coll; //std::vector<int,MyAlloc<int>> coll;

Lambdas

仿函数式,定义及相关使用:

auto l = [] (const std::string& s) {    std::cout << s << std::endl;};l("hello lambda"); // prints ‘‘hello lambda’’//或者[] {    std::cout << "hello lambda" << std::endl;} (); // prints ‘‘hello lambda’’

可以使用capture获取外部的参数,可以使用值传递[=]与引用[&]两种方式。

int x=0;int y=42;auto qqq = [x, &y] {    std::cout << "x: " << x << std::endl;    std::cout << "y: " << y << std::endl;    ++y; // OK};x = y = 77;qqq();qqq();std::cout << "final y: " << y << std::endl;

使用值传递的值,抓取后会“停留”在抓取的那个时候,不会外界值的改变而改变, 而使用引用传递则会因为外部改变而改变。
output:

x: 0y: 77x: 0y: 78final y: 79

加multable, 可使其内部,通过值传递进来的值,对其进行修改:

int id = 0;auto f = [id] () mutable {    std::cout << "id: " << id << std::endl;    ++id; // OK};id = 42;f();f();f();std::cout << id << std::endl;//output id: 0id: 1id: 242

Keyword decltype

decltype作为操作符,用于查询表达式的数据类型

Scoped Enumerations

使用:

//定义enum class Salutation : char { mr, ms, co, none };//用Salutation::mr

Nontype Template Parameters

例子:

bitset<32> flags32; // bitset with 32 bitsbitset<50> flags50; // bitset with 50 bits

Default Template Parameters

用法:

template <typename T, typename container = vector<T>>class MyClass;MyClass<int> x1; // equivalent to: MyClass<int,vector<int>>

Member Templates

成员模板函数:

class MyClass {    //...    template <typename T>    void f(T);};

一些使用需要注意的地方:

template <typename T>class MyClass {private:    T value;public:    void assign (const MyClass<T>& x) { // x must have same  type as *this    value = x.value;}//...};//使用void f(){    MyClass<double> d;    MyClass<int> i;    d.assign(d); // OK    d.assign(i); // ERROR: i is MyClass<int>                 // but MyClass<double> is required}//解决方法template <typename T>class MyClass {private:    T value;public:    template <typename X> // member template    void assign (const MyClass<X>& x) { // allows different template types    value = x.getValue();}T getValue () const {    return value;}//...};void f(){    MyClass<double> d;    MyClass<int> i;    d.assign(d); // OK    d.assign(i); // OK (int is assignable to double)}

模板构造函数使用:

template <typename T>class MyClass {public:    // copy constructor with implicit type conversion    // - does not suppress implicit copy constructor    template <typename U>    MyClass (const MyClass<U>& x);    //...};void f(){    MyClass<double> xd;    //...    MyClass<double> xd2(xd); // calls implicitly generated copy constructor    MyClass<int> xi(xd); // calls template constructor    //...}
0 0
原创粉丝点击