- 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);

1214

被折叠的 条评论
为什么被折叠?



