C++类型操作
2016-05-16 00:08
330 查看
C++中,对类型进行操作的有 typedef,using,decltype。
decltype 不对表达式求值,这一点同sizeof 一样。所以如果表达式中包含函数调用,并不需要看到该函数的定义实现,只需看到声明即可。
这里 NonDefault() 都不存在,所以虽然不发生调用的过程,仍然会有编译错误。这种情况还有构造函数被标记为 = delete,一样相当于不存在。
declval<T>() 也可以写成 declval(T) ,等价的。
declval<T>() 的类型 为 类型T加上右值引用,这里存在引用折叠,只有当T是左值引用类型时,返回的是左值引用,其他情况,返回的都是右值引用类型。
C++中的引用语义使得引用变量总是代表其所绑定的对象,通过类型转换,可以将引用变量绑定到对象地址开始的部分内存上。即将对象转换为引用类型,相当于为对象绑定了一个引用变量。
c++中的变量名本来就对应着存储该对象的一块内存(包括数组名),而不是现代编程语言中的名称与对象分离。将对象转化为引用就是将对象的起始地址开始的内存绑定到引用上。
输出:eeff . //这里是小端模式
需要说明的地方:C++11中存在左值和右值引用,对于上边的例子,reinterpret_cast<char&&>(i) 得到的是右值,reinterpret_cast<char&>(i)得到的却是左值,虽然得到的值都是匿名的对象。这也是为啥标准库中的 move() 函数其实进行的操作就是转换为右值引用。有名对象 ==》左值, 逆否命题: 右值==》匿名对象。补充的:匿名对象也可以是左值。
更细的值分类,可以看这里。
或者用指针的方式来表达绑定的过程:
或者用C语言的表达方式:
decltype 不对表达式求值,这一点同sizeof 一样。所以如果表达式中包含函数调用,并不需要看到该函数的定义实现,只需看到声明即可。
struct Default { int foo() const {return 1;} }; struct NonDefault { NonDefault(const NonDefault&) {} int foo() const {return 1;} }; int main() { decltype(Default().foo()) n1 = 1; // int n1 // decltype(NonDefault().foo()) n2 = n1; // error: no default constructor decltype(std::declval<NonDefault>().foo()) n2 = n1; // int n2 std::cout << "n2 = " << n2 << '\n'; }
这里 NonDefault() 都不存在,所以虽然不发生调用的过程,仍然会有编译错误。这种情况还有构造函数被标记为 = delete,一样相当于不存在。
declval<T>() 也可以写成 declval(T) ,等价的。
declval<T>() 的类型 为 类型T加上右值引用,这里存在引用折叠,只有当T是左值引用类型时,返回的是左值引用,其他情况,返回的都是右值引用类型。
C++中的引用语义使得引用变量总是代表其所绑定的对象,通过类型转换,可以将引用变量绑定到对象地址开始的部分内存上。即将对象转换为引用类型,相当于为对象绑定了一个引用变量。
c++中的变量名本来就对应着存储该对象的一块内存(包括数组名),而不是现代编程语言中的名称与对象分离。将对象转化为引用就是将对象的起始地址开始的内存绑定到引用上。
int i = 0xeedd; char& ref = reinterpret_cast<char&>(i); ref = 0xff; printf("%x", i);
输出:eeff . //这里是小端模式
需要说明的地方:C++11中存在左值和右值引用,对于上边的例子,reinterpret_cast<char&&>(i) 得到的是右值,reinterpret_cast<char&>(i)得到的却是左值,虽然得到的值都是匿名的对象。这也是为啥标准库中的 move() 函数其实进行的操作就是转换为右值引用。有名对象 ==》左值, 逆否命题: 右值==》匿名对象。补充的:匿名对象也可以是左值。
更细的值分类,可以看这里。
或者用指针的方式来表达绑定的过程:
int i = 0xeedd; char& p = *(char*)&i; p = 0xcc; printf("%x", i);
或者用C语言的表达方式:
char* ptr = (char*)&i; *ptr = 0xaa; printf("%x", i);
相关文章推荐