目录
8-2.使用C++11标准定义的alignof函数查看数据的对齐方式
8-4.使用C++11新提供的修饰符alignas指定某个数据结构的对齐方式
8-6.采用模板的方式实现一个固定容量但是大小随着所用的数据类型变化的容器类型(我的编译器与书上提供结果不符合)
8-7.使用std::align对指定的内存进行指定的内存对齐操作(但是我的编译器好像并没有按需要改成功,虽然没有报错)
8-8.使用aligned_storage使数据类型产生要求更加严格的对齐要求
8-9.扩展语法中的__attribute__属性中的const应用举例
8-10.扩展语法中的__attribute__属性中的__declspec应用举例
8-11.C++11中预定义的通用属性[[noreturn]]的用法简单演示
8-12.C++11中预定义的通用属性[[noreturn]]的一个不严谨用法展示
8-13.C++11中预定义的通用属性[[carries_dependency]]的一个用例展示(支持度不是很好,要看平台的)
8-15.环境没有问题的情况下,Unicode就能良好运行吗?
8-16.mbrtomb(char32转成多字节字符串)函数的一个用例展示(我的机器上的编译器还不能支持)
8-18.利用一些简单设定来实现stream自动地进行一些编码的转换
8-19.wstring_convert可支持使用from_bytes来完成逆向的编码转换,但书中及我个人的编译器都不支持
8-20.C++11中使用R来实现对原生字符串的支持的一个简单示例
8-22.原生字符串字面量也像C的字符串字面量一样遵从连接规则
8-1.回顾字节对齐的经典案例
#include <iostream>
using namespace std;
struct HowManyBytes{
char a;
int b;
};
int main(){
cout << "sizeof(char) = " << sizeof(char) <<endl;
cout << "sizeof(int) = " << sizeof(int) <<endl;
cout << "sizeof(HowManyBytes) = " << sizeof(HowManyBytes) <<endl;
cout << endl;
cout << "offset of char a " << offsetof(HowManyBytes,a) <<endl;
cout << "offset of char b " << offsetof(HowManyBytes,b) <<endl;
return 0;
}
/*
编译选项:g++ -std=c++11 8-1-1.cpp
代码清单: 8-1
代码功能: 回顾字节对齐的经典案例
*/
8-2.使用C++11标准定义的alignof函数查看数据的对齐方式
#include <iostream>
using namespace std;
struct ColorVector{
double r;
double g;
double b;
double a;
};
int main(){
cout << "Alignof(ColorVector)" << alignof(ColorVector) <<endl;
return 1;
}
/*
编译选项:g++ -std=c++11 8-1-1.cpp
代码清单: 8-2
代码功能: 使用C++11标准定义的alignof函数查看数据的对齐方式
*/
8-3.alignof的一些简单的用法及注意点
#include <iostream>
using namespace std;
class InComplete;
struct Completed{};
int main(){
int a;
long long b;
auto & c = b;
char d[1024];
// 对内置类型和完整类型使用alignof
cout << alignof(int)<<endl; // 4
cout << alignof(Completed)<<endl;// 1
// 对变量,引用或者数组使用alignof
cout << alignof(a)<<endl // 4
<< alignof(b)<<endl // 8
<< alignof(c)<<endl // 8,与b相同
<< alignof(d)<<endl;// 1,与元素要求相同
// cout << alignof(InComplete)<<endl; // 本句无法通过编译,InComplete类型不完整
return 0;
}
/*
编译选项:g++ -std=c++11 8-1-4.cpp
代码清单: 8-4
代码功能: alignof的一些简单的用法及注意点
*/
8-4.使用C++11新提供的修饰符alignas指定某个数据结构的对齐方式
#include <iostream>
using namespace std;
class InComplete;
struct Completed{};
int main(){
int a;
long long b;
auto & c = b;
char d[1024];
// 对内置类型和完整类型使用alignof
cout << alignof(int)<<endl; // 4
cout << alignof(Completed)<<endl;// 1
// 对变量,引用或者数组使用alignof
cout << alignof(a)<<endl // 4
<< alignof(b)<<endl // 8
<< alignof(c)<<endl // 8,与b相同
<< alignof(d)<<endl;// 1,与元素要求相同
// cout << alignof(InComplete)<<endl; // 本句无法通过编译,InComplete类型不完整
return 0;
}
/*
编译选项:g++ -std=c++11 8-1-4.cpp
代码清单: 8-4
代码功能: 使用C++11新提供的修饰符alignas指定某个数据结构的对齐方式
*/
8-5.alignas的用法注意点
alignas(double) void f(); // 错误,alignas不能修饰函数
alignas(double) unsigned char c[sizeof(double)]; // 正确
extern unsigned char c[sizeof(double)];// 我的环境下的clang++和g++下没有报错和警告
alignas(float) extern unsigned char c[sizof(double)]; // 错误:不同对齐方式的变量定义
/*
编译选项:g++ -std=c++11 8-1-5.cpp
clang++ -std=c++11 8-1-5.cpp
代码清单: 8-5
代码功能: alignas的用法注意点
*/
8-6.采用模板的方式实现一个固定容量但是大小随着所用的数据类型变化的容器类型(我的编译器与书上提供结果不符合)
#include <iostream>
using namespace std;
struct alignas(alignof(double)*4) ColorVector{
double r;
double g;
double b;
double a;
};
template <typename T>
class FixedCapacityArray{
public:
void push_back(T t)
char alignas(T) data[1024] ={0};
};
int main(){
FixedCapacityArray<char> arrCh;
cout << "alignof(char):" << alignof(char) <<endl;
cout << "alignof(arrCh.data):" << alignof(arrCh.data) <<endl;
FixedCapacityArray<ColorVector> arrCV;
cout << "alignof(ColorVector):" << alignof(ColorVector) <<endl;
cout << "alignof(arrCV.data):" << alignof(arrCV.data) <<endl;
return 1;
}
/*
编译选项:g++ -std=c++11 8-1-6.cpp
代码清单: 8-5
代码功能: 采用模板的方式实现一个固定容量但是大小随着所用的数据类型变化的容器类型(我的编译器与书上提供结果不符合)
*/
8-7.使用std::align对指定的内存进行指定的内存对齐操作(但是我的编译器好像并没有按需要改成功,虽然没有报错)
#include <iostream>
#include <memory>
using namespace std;
struct alignas(alignof(double)*4) ColorVector{
double r;
double g;
double b;
double a;
};
int main(){
size_t const size = 100;
ColorVector * const vec = new ColorVector[size];
void* p = vec;
size_t sz = size;
void* aligned = align(alignof(double)*4,size,p,sz);
cout << alignof(double)<<endl;
cout << alignof(p)<<endl;
if(aligned != nullptr)
cout << alignof(p)<<endl;
else
cout << "aligned is NULL" << endl;
}
/*
前置知识点:
void* align(std::size_t alignment,std::size_t size,void*& ptr,std::size_t& space)
在ptr指向的大小为space的内存中进行对齐方式的挑战,将ptr开始的size大小的数据调整为按照
alignment对齐.
编译选项:g++ -std=c++11 8-1-7.cpp
代码清单: 8-6
代码功能: 使用std::align对指定的内存进行指定的内存对齐操作(但是我的编译器好像并没有按需要改成功,虽然没有报错)
代码的问题:
*/
8-8.使用aligned_storage使数据类型产生要求更加严格的对齐要求
#include <iostream>
#include <type_traits>
using namespace std;
struct IntAligned{
int a;
char b;
};
// 使用aligned_storage使其对齐要求更加严格
typedef aligned_storage<sizeof(IntAligned),alignof(long double)>::type StrictAligned;
int main(){
StrictAligned sa;
IntAligned* pia = new(&sa) IntAligned;
cout << alignof(IntAligned)<<endl; // 4
cout << alignof(StrictAligned)<<endl; // 16
cout << alignof(*pia)<<endl; // 4
cout << alignof(sa)<<endl; // 16
return 0;
}
/*
编译选项:g++ -std=c++11 8-1-8.cpp
代码清单: 8-8
代码功能: 使用aligned_storage使数据类型产生要求更加严格的对齐要求
*/
8-9.扩展语法中的__attribute__属性中的const应用举例
extern int area(int n) __attribute__((const));// const属性告诉编译器,本函数的返回值只依赖于输入,不会改变任何函数外的数据
int main(){
int i;
int areas = 0;
for(i = 0;i< 10;i++){
areas += area(3) * i;
}
}
/*
编译选项:g++ -std=c++11 8-2-1.cpp -c
代码清单: 8-9
代码功能: 扩展语法中的__attribute__属性中的const应用举例
*/
8-10.扩展语法中的__attribute__属性中的__declspec应用举例
__declspec(align(32)) struct Struct32{ // 结构体Struct3被对齐到32字节的地址边界
int i;
double d;
};
/*
编译选项:微软平台下
代码清单: 8-10
代码功能: 扩展语法中的__attribute__属性中的__declspec应用举例
*/
8-11.C++11中预定义的通用属性[[noreturn]]的用法简单演示
void DoSomething1();
void DoSomething2();
[[ noreturn ]] void ThrowAway(){
throw "exception"; // 控制流跳转到异常处理
}
void Func(){
DoSomething1();
ThrowAway();
DoSomething2();// 该函数不可到达
}
/*
编译选项:clang++ -std=c++11 8-2-3.cpp
g++ -std=c++11 8-2-3.cpp
代码清单: 8-11
代码功能: C++11中预定义的通用属性[[noreturn]]的用法简单演示
*/
8-12.C++11中预定义的通用属性[[noreturn]]的一个不严谨用法展示
#include <iostream>
using namespace std;
[[noreturn]] void Func(int i){
if(i < 0) // 当参数i的值为0的时候,该函数的行为不可估计
throw "negative";
else if(i> 0)
throw "positive";
}
int main(){
Func(0);
cout << "Returned" <<endl; // 无法执行该句
return 1;
}
/*
编译选项:clang++ -std=c++11 8-2-4.cpp
g++ -std=c++11 8-2-4.cpp
代码清单: 8-12
代码功能: C++11中预定义的通用属性[[noreturn]]的一个不严谨用法展示
*/
8-13.C++11中预定义的通用属性[[carries_dependency]]的一个用例展示(支持度不是很好,要看平台的)
#include <iostream>
#include <atomic>
using namespace std;
atomic<int*> p1;
atomic<int*> p2;
atomic<int*> p3;
atomic<int*> p4;
void func_in1(int* val){
cout << *val << endl;
}
void func_in2(int* [[carries_dependency]] val){
p2.store(val,memory_order_release);
cout << *p2 << endl;
}
[[carries_dependency]] int* func_out(){
return (int *)p3.load(memory_order_consume);
}
void Thread(){
int* p_ptr1 = (int *)p1.load(memory_order_consume); // L1
cout << *p_ptr1 << endl; // L2
func_in1(p_ptr1); // L3
func_in2(p_ptr1); // L4
int * p_ptr2 = func_out(); // L5
p4.store(p_ptr2,memory_order_release); // L6
cout << *p_ptr2 << endl;
}
/*
编译选项:clang++ -std=c++11 8-2-5.cpp -c(报错)
g++ -std=c++11 8-2-5.cpp -c (有警告)
代码清单: 8-13
代码功能: C++11中预定义的通用属性[[carries_dependency]]的一个用例展示(支持度不是很好,要看平台的)
*/
8-14.展示Unicode字符串的一些用法和注意事项
#include <iostream>
using namespace std;
int main(){
char utf8[]=u8"\u4F60\u597D\u554A";
char16_t utf16[] = u"hello";
char32_t utf32[] = U"hello equals \u4F60\u597D\u554A";
cout << utf8 << endl; // 期望打印出“hello”,我的实验机器上正好符合期望
cout << utf16 << endl; // 期望打印出“hello”,我的实验机器上不能正常打印出,还需要其他条件
cout << utf32 << endl; // 期望打印出“hello equals你好啊”,我的实验机器上不能正常打印出,还需要其他条件
//char32_t u2[] = u"hello";// error,一旦使用了Unicode字符串前缀,这个字符创的类型就确定了,只能放在相应类型的数组中
//char u3[] = U"hello"; // error,一旦使用了Unicode字符串前缀,这个字符创的类型就确定了,只能放在相应类型的数组中
//char16_t u4 = u8"hello"; // error,一旦使用了Unicode字符串前缀,这个字符创的类型就确定了,只能放在相应类型的数组中
return 0;
}
/*
编译选项: g++ -std=c++11 8-3-1.cpp
代码清单: 8-14
代码功能: 展示Unicode字符串的一些用法和注意事项
*/
8-15.环境没有问题的情况下,Unicode就能良好运行吗?
#include <iostream>
using namespace std;
int main(){
char utf8[] = u8"\u4F60\u597D\u554A";
char16_t utf16[]=u"\u4F60\u597D\u554A";
cout << utf8 << endl; // 输出“你好啊”
cout << sizeof(utf8)<<endl; // 10
cout << sizeof(utf16)<<endl; // 8
cout << utf8[1]<<endl; // 输出不可见字符,我们将UTF=8编码的数据放在了一个char类型中,所以utf8[1]只是指向了一个UTF-8字符3字节中的第二位,因此输出不正常
cout << utf16[1]<<endl; // 输出22909(0x597D)
return 0;
}
/*
编译选项: g++ -std=c++11 8-3-2.cpp
代码清单: 8-15
代码功能: 环境没有问题的情况下,Unicode就能良好运行吗?
*/
8-16.mbrtomb(char32转成多字节字符串)函数的一个用例展示(我的机器上的编译器还不能支持)
#include <iostream>
#include <cuchar>
using namespace std;
int main(){
char16_t utf16[] = u"\u4F60\u597D\u554A";
char mbr[sizeof(utf16)*2] = {0};
mbstate_t s;
mbrtomb(mbr,utf16,&s);
cout<< mbr <<endl;
return 0;
}
/*
编译选项: g++ -std=c++11 8-3-3.cpp
代码清单: 8-16
代码功能: mbrtomb(char32转成多字节字符串)函数的一个用例展示(我的机器上的编译器还不能支持)
*/
8-17.测试机器支持字符编码转换的方法的一个简单示例
#include <iostream>
#include <locale>
using namespace std;
int main(){
locale lc("en_US.UTF-8");
bool can_cvt = has_facet<codecvt<wchar_t,char,mbstate_t>>(lc);
if(!can_cvt)
cout<<"Do not support char-wchar_t facet!"<<endl;
can_cvt = has_facet<codecvt<char16_t,char,mbstate_t>>(lc);
if(!can_cvt)
cout<<"Do not support char16_t facet!"<<endl;
can_cvt = has_facet<codecvt<char32_t,char,mbstate_t>>(lc);
if(!can_cvt)
cout<<"Do not support char32_t facet!"<<endl;
can_cvt = has_facet<codecvt<char,char,mbstate_t>>(lc);
if(!can_cvt)
cout<<"Do not support char facet!"<<endl;
return 0;
}
/*
编译选项: g++ -std=c++11 8-3-4.cpp
代码清单: 8-17
代码功能: 测试机器支持字符编码转换的方法的一个简单示例
*/
8-18.利用一些简单设定来实现stream自动地进行一些编码的转换
#include <iostream>
#include <fstream>
#include <string>
#include <locale>
#include <iomanip>
using namespace std;
int main(){
// UTF-8字符串,“\x7a\xc3\x9f\xe6\xb0\xf0\x9d\x84\x8b”
ofstream("text.txt")<<u8"z\u00df\u6c34\U0001d10b";
wifstream fin("text.txt");
// 这个locale的facet-convert<wchar_t,char,mbstate_t>可以将UTF-8转化成UTF-32
fin.imbue(locale("en_US.UTF-8"));
cout <<"The UTF-8 file contains the following wide characters:" <<endl;
for(wchar_t c;fin>>c)
cout<<"U+"<<hex<<setw(4)<<setfill('0'<<c<<'\n');
}
/*
编译选项: g++ -std=c++11 8-3-5.cpp
代码清单: 8-18
代码功能: 利用一些简单设定来实现stream自动地进行一些编码的转换
*/
8-19.wstring_convert可支持使用from_bytes来完成逆向的编码转换,但书中及我个人的编译器都不支持
#include <cvt/wstring>
#include <codecvt>
#include <iostream>
using namespace std;
int main(){
wstring_convert<codecvt_utf8<wchar_t>> myconv;
string mbstring = myconv.to_bytes(L"Hello\n");
cout << mbstring;
}
/*
编译选项: g++ -std=c++11 8-3-6.cpp
代码清单: 8-19
代码功能: wstring_convert可支持使用from_bytes来完成逆向的编码转换,但书中及我个人的编译器都不支持
*/
8-20.C++11中使用R来实现对原生字符串的支持的一个简单示例
#include <iostream>
using namespace std;
int main(){
cout << R"(hello,\n
world)"<<endl;
return 0;
}
/*
编译选项:g++ -std=c++11 8-4-1.cpp
代码清单: 8-4-1
代码功能: C++11中使用R来实现对原生字符串的支持的一个简单示例
*/
8-21.使用了原生字符串之后,转义字符就不再有效了
#include <iostream>
using namespace std;
int main(){
cout << u8R"(\u4F60,\n
\u597D)"<<endl;
cout << u8R"(你好)"<<endl;
cout << sizeof(u8R"(hello)")<<"\t"<<u8R"(hello)"<<endl;
cout << sizeof(uR"(hello)")<<"\t"<<uR"(hello)"<<endl;
cout << sizeof(UR"(hello)")<<"\t"<<UR"(hello)"<<endl;
return 0;
}
/*
编译选项:g++ -std=c++11 8-4-2.cpp
代码清单: 8-4-2
代码功能: 使用了原生字符串之后,转义字符就不再有效了
*/
8-22.原生字符串字面量也像C的字符串字面量一样遵从连接规则
#include <iostream>
using namespace std;
int main(){
char u8string[] = u8R"(你好)" "=hello";
cout << u8string << endl; // 输出"你好 = hello"
cout << sizeof(u8string) << endl; // 15
return 0;
}
/*
编译选项:g++ -std=c++11 8-4-3.cpp
代码清单: 8-4-3
代码功能: 原生字符串字面量也像C的字符串字面量一样遵从连接规则
*/