C++ 11/14 3

来源:互联网 发布:matlab绘制矩阵图 编辑:程序博客网 时间:2024/05/21 22:58
  • Rvalue and Lvalue
  • std::forward
  • moveable string
  • mutable
  • constexpr
  • 11 编程规范 1.类型处理
  • auto /模板函数类型推导

Rvalue and Lvalue

Rvalue reference : a new reference type to solve unnecessary copy
Lvalue 可以出现在operator = 左右
Rvalue 之可以出现在operator = 右边(临时对象都是右值)
但是此时sting() = “aaa”, str1 + str2 = “aaa”可以编译违背上述定义
另一种说法可以取地址的都是左值。
以上两种说法属于学术之争不做深究。

补充函数返回值:

int foo() {return 1;}int x = foo()//okint(*)() x = &foo;//okint x = &foo()//error 此处语义为对foo()的返回值取地址,其返回值为一个右值无法取地址foo()= 7 //error

补充scott-meyers关于universal reference 解释
https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
归根结底需要推导的就是universal,给出足够信息不需要推导的就是rvalue。

std::forward

用来完美转发类型

// forward example#include <utility>      // std::forward#include <iostream>     // std::cout// function with lvalue and rvalue reference overloads:void overloaded (const int& x) {std::cout << "[lvalue]";}void overloaded (int&& x) {std::cout << "[rvalue]";}// function template taking rvalue reference to deduced type:template <class T> void fn (T&& x) {  overloaded (x);                   // always an lvalue  overloaded (std::forward<T>(x));  // rvalue if argument is rvalue}int main () {  int a;  std::cout << "calling fn with lvalue: ";  fn (a);  std::cout << '\n';  std::cout << "calling fn with rvalue: ";  fn (0);  std::cout << '\n';  return 0;}

move 源代码

template <typename _Tp>    constexpr typename std::remove_referece<_Tp>::type&&    move(_Tp&& __T)noexcept    {                                                                           return satic_cast<typename std::remove_reference<_Tp>::type&&> (__t);    }

forward代码

template<typename _Tp>constexpr _Tp&&    forward(typename std::remove_referece<_Tp>::type& _t)noexcept{    return static_cast<_Tp&&>(_t);}template <typename _Tp>constexpr _Tp&&    forward(typename std::remove_referece<_Tp>::type&& __t)noexcept{    satic_assert(!std::islvaue_referece<_Tp>::value,"template argument substituting is an lvalue reference type");    return satic_cast<_Tp&&>(__t);}

参考:
http://shaoyuan1943.github.io/2016/03/26/explain-move-forward/

moveable string

class MoveableString{private:    char* _data;    size_t _len;    void _init_data(const char* s){    _data =new char[_len+1];    memcpy(data,s,_len);    _data[_len] = '\0';}public:    MoveableString():_data(std::nullptr),_len(0){}    MoveableString(const char* p ): _len(strlen(p){    _init_data(p);    }    MoveableString(const MoveableString& str):_len(str._len){    _init_data(str._data);    }    MoveableString(MoveableString&& str)    noexcept:_data(str._data),_len(str._len){        str._len = 0;        str._data = std::nullptr;    }    MoveableString& operator= (const MoveableString& str) {        if (this != &str){            if(_data)                delete[] _data;            _len = str._len;            _init_data(str._data);        }        return *this;    }    MoveableString& operator= (MoveableString&& str)noexcept {    if(this != &str){        if(_data)            delete[] _data;        _data = str._data;        _len = str._len;        str._data = nullptr;        str._len = 0;        }    return *this;    }   };//或者使用std::swap 实现也可以

mutable

const int * px = &x//指针本身可以改变,但是指向的内容不能更改int* const py = &y//指针本身不能只想别处,但是其内容可以更改class c{mutable int x;public:    void f() const {        this->x = 222;//此处想修改其值必须在x声明前面加上mutable    }};

mutable一般只用在类内部,用在类外声明错误。

constexpr

constexpr是C++11中新增的关键字,其语义是“常量表达式”,也就是在编译期可求值的表达式。
最基础的常量表达式就是字面值或全局变量/函数的地址或sizeof等关键字返回的结果,而其它常量表达式都是由基础表达式通过各种确定的运算得到的。
constexpr值可用于enum、switch、数组长度等场合。
参考:
http://www.cnblogs.com/td15980891505/p/5137013.html

11 编程规范 1.类型处理

不确定用什么容器的时候首选vector
尽量避免隐式转型
推倒获取类型

template<typename>class ID;//无需定义仅为了引发编译错误,在编译期间显示变量类型ID<decltype(x)> xtype;//引发编译器错误,可以看到x 的type

aito d = [](const int *&p1, const int *&p2) {return *p1 <*p2;};传递指针的引用否则会产生指针临时变量,无法真正赋值,c 中没有& 只能**
C++14lambda形参表可以用auto,11,不可以

vector<bool>????是vector 的一个bool特化 内部有一个代理类 bit_reference  vector<boo> vb {true,false}; 对于auto v = vb[0]; decltype(v) 得到std::__Bit_reference 此时应该 auto v= static_cast<bool> vb[0];来正确得到vb[0]的类型 而不应该使用  bool v = vb[0];避免一切形式隐式转换 。
template<typename T>void func(T){}void func(T&){}传入实参若带const推导出来类型并不相同传入 const 会不会保留取决于传入的是不是* & ,*& 指向同一块内存 const保留,否则不保留。auto 推导和函数模板推导基本一样 除了initializer_list. auto 可以, 函数模板不可以。 && 万能引用 遇左则左遇右则右。 某种意义上说可以取址& 为左值 c/c++ 数组类型可以退化成指针 按引用传递则不会退化

萃取机来萃取数组长度

template<typename _type,std::size_t _size>constexpr auto traits_size(_type(&)[_size]) noexcept{    return _size;}//传入实参必须是数组不能使已经退化了的指针char a[] = {"123444"};std::size_t len_of_a = traits_size(a);
原创粉丝点击