C++ 11/14 3

  • 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()//ok
int(*)() x = &foo;//ok
int 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);

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值