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

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, ambiguous
f(nullptr); //call f(void*) 

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

namespace std
{
  typedef decltype(nullptr) nullptr_t;
}

auto

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

auto i; //error
auto 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 value
int j{}; // j is initialized by 0
int* p; // p has undefined value
int* q{}; // q is initialized by nullptr

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

int x1(5.3); // OK, but OUCH: x1 becomes 5
int x2 = 5.3; // OK, but OUCH: x2 becomes 5
int x3{5.0}; // ERROR: narrowing
int x4 = {5.3}; // ERROR: narrowing
char c1{7}; // OK: even though 7 is an int, this is not narrowing
char c2{99999}; // ERROR: narrowing (if 99999 doesn’t fit into a char)
std::vector<int> v1 { 1, 2, 4, 5 }; // OK
std::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.5
hello
0000000101111001
42

Alias Templates (Template Typedef)

用法:

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

Vec<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: 0
y: 77
x: 0
y: 78
final 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: 0
id: 1
id: 2
42

Keyword decltype

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

Scoped Enumerations

使用:

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

Nontype Template Parameters

例子:

bitset<32> flags32; // bitset with 32 bits
bitset<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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值