VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 432|回复: 1

[原创] 现代C++的技巧-大浪淘金

[复制链接]
75_avatar_middle
最佳答案
0 
在线会员 发表于 2019-5-7 23:30:57 | 显示全部楼层 |阅读模式

现代C++的一些技巧-大浪淘金
         
参考 Welcome Back to C++ (Modern C++)
https://docs.microsoft.com/en-us ... tudio-2013/hh279654(v%3dvs.120)
例子有所修改。

测试要添加包含
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <memory>

1)一般情况下,避免将 using 指令放置在头文件(*.h) 中,
因为任何包含该标头的文件都会将命名空间中的所有内容引入范围,
这将导致非常难以调试的名称隐藏和名称冲突问题。
using namespace std;

2)与C相关的包含,函数,变量,可以这样表述
extern "C" {
   #include <stdio.h>
}

3)几种容器用法,这已经很常见了。
a)vector
vector<string> apples;
apples.push_back("Granny Smith");
b)map
map<string, string> apple_color;
apple_color["Granny Smith"] = "Green";
c)unordered_map
unordered_map<char, int> umap;
umap.insert(unordered_map<char, int>::value_type('a', 1));
umap.insert(unordered_map<char, int>::value_type('b', 2));
umap.insert(unordered_map<char, int>::value_type('c', 3));
cout << "c1.at('a') == " << umap.at('a') << endl;
cout << "c1.at('b') == " << umap.at('b') << endl;
cout << "c1.at('c') == " << umap.at('c') << endl;

4)smart指针,比较流行,特别在DX12SDK中
a)unique_ptr,make_unique
data a[4] = {
        { "1","aaaa", "aaaa"},
        { "2","bbbb", "bbbb" },
        { "3","cccc", "cccc" },
        { "4","dddd", "dddd" }
};
vector<unique_ptr<data>> songs;
songs.push_back(make_unique<data>(a[0]));
songs.push_back(make_unique<data>(a[1]));
songs.push_back(make_unique<data>(a[2]));
songs.push_back(make_unique<data>(a[3]));
cout << "no \tArtist \tTitle "  << endl;
for (const auto& song : songs)
{
   cout <<  song->s1<< "\t" << song->s2 << "\t" << song->s3 << endl;
}
b)shared_ptr,make_shared
data b[3] = {
        {"1111", "aaaaaaa","111111"},
        {"2222", "bbbbbbb","222222"},
        {"3333", "ccccccc","333333"}
};
vector<shared_ptr<data>> v{
        make_shared<data>(b[0]),
        make_shared<data>(b[1]),
        make_shared<data>(b[2])
};
for (const auto& s : v)
{
   cout << s->s1 <<  ":" << s->s2 << ":" << s->s3 << endl;
}

5)lambda表达式,写出来很多人都看不懂。高深隐晦,大师的长相。
auto f1 = [](int x, int y) { return x + y; };
cout << f1(2, 3) << endl;
int k = [](int x, int y) { return x + y; }(5, 4);
cout << k << endl;
int m = 0;
int n = 0;
[&, n](int a) mutable { m = ++n + a; }(4);
cout << m << endl << n << endl;

6)mutable修饰字,mutable翻译是易变的;很可能改变的
放在非静态,非常量的类数据成员,可以由常量成员函数赋值
也可以由非常量成员函数赋值。第三方SDK代码中常用。
class ca
{
   mutable string s1;
   int a;
   string s2;
public:
   void setcs() const
   {
        s1 = "aaaaa";
   }
   void show() {
        cout << "s1=" << s1 << endl;
        cout << "s2=" << s2 << endl;
        s1 = "ccccc";//强制赋值,它是可以地
        cout << "s1=" << s1 << endl;
   }
   void setvs()/* const*/ {
        s2 = "bbbbb";//如果不注释const,此处编译器报错,即不能通过常量成员函数赋值
   }
};
ca aa;
aa.setcs();
aa.setvs();
aa.show();

7)const修饰, 一般人都会看晕地,包括我自己,是MSDN地,只不过我总结地放在一起。
const char cch = 'A';
char ch = 'B';
//正确
const char *pch1 = &cch;
const char *const pch4 = &cch;
const char *pch5 = &ch;
char *pch6 = &ch;
char *const pch7 = &ch;
const char *const pch8 = &ch;
//加注释地是编译器指明错误地
//char *pch2 = &cch;  
//char *const pch3 = &cch;   
char *pch2=nullptr;
char *const pch3=nullptr;
pch1  = &ch;    // OK: pointer not declared const
*pch2 = 'A';      // OK: normal pointer
pch2  = &ch;    // OK: normal pointer
*pch3 = 'A';      // OK: object not declared const
//加注释地是编译器指明错误地
//*pch1 = 'A';    // Error: object declared const
//pch3  = &ch;  // Error: pointer declared const
//*pch4 = 'A';    // Error: object declared const
//pch4  = &ch;  // Error: pointer declared const

8)自动变量在遍历4种用法,结果都是一样。
int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int y : x) {
  cout << y << " ";
}
cout << endl;
for (auto y : x) {
  cout << y << " ";
}
cout << endl;
for (auto &y : x) {
  cout << y << " ";
}
cout << endl;
for (const auto &y : x) {
  cout << y << " ";
}
cout << endl;

9)文本自动变量声明,当满篇都是auto的时候,老程序员都看不懂了。
// Character literals
auto c0 = 'A';      // char
auto c1 = u8'A';  // char
auto c2 = L'A';    // wchar_t
auto c3 = u'A';   // char16_t
auto c4 = U'A';  // char32_t

// String literals
auto s0 = "hello";   // const char*
auto s1 = u8"hello"; // const char*, encoded as UTF-8
auto s2 = L"hello";  // const wchar_t*
auto s3 = u"hello";  // const char16_t*, encoded as UTF-16
auto s4 = U"hello";  // const char32_t*, encoded as UTF-32

// Raw string literals containing unescaped \ and "
auto R0 = R"("Hello \ world")";   // const char*
auto R1 = u8R"("Hello \ world")"; // const char*, encoded as UTF-8
auto R2 = LR"("Hello \ world")";  // const wchar_t*
auto R3 = uR"("Hello \ world")";  // const char16_t*, encoded as UTF-16
auto R4 = UR"("Hello \ world")";  // const char32_t*, encoded as UTF-32

// Combining string literals with standard s-suffix
auto S0 = "hello"s;      // std::string
auto S1 = u8"hello"s;  // std::string
auto S2 = L"hello"s;    // std::wstring
auto S3 = u"hello"s;   // std::u16string
auto S4 = U"hello"s;  // std::u32string

// Combining raw string literals with standard s-suffix
auto S5 = R"("Hello \ world")"s;     // std::string from a raw const char*
auto S6 = u8R"("Hello \ world")"s; // std::string from a raw const char*, encoded as UTF-8
auto S7 = LR"("Hello \ world")"s;   // std::wstring from a raw const wchar_t*
auto S8 = uR"("Hello \ world")"s;   // std::u16string from a raw const char16_t*, encoded as UTF-16
auto S9 = UR"("Hello \ world")"s;  // std::u32string from a raw const char32_t*, encoded as UTF-32

10)数字分隔符
//数字分隔符:可以使用单引号字符 (撇号) 分隔中较大的数,
//以使其更易于供人阅读的位置值。 分隔符不会对编译产生任何影响。
//你在数值上面不要乱加,会扰乱阅读者的心神。不知道你在干什么,虽然不影响结果。
long long i = 24'847'458'121;
cout << "i=" << i << endl;

11)C++位域
struct Date {
        unsigned nWeekDay   : 3;    // 0..7   (3 bits)
        unsigned nMonthDay : 6;    // 0..31  (6 bits)
        unsigned                     : 0;    // Force alignment to next boundary.
        unsigned nMonth       : 5;    // 0..12  (5 bits)
        unsigned nYear           : 8;    // 0..100 (8 bits)
};
赋值,取值很简单,但理解它的数据就不很简单。
为了调试在程序首添加
#include <bitset>
using std::bitset;
再添加下面测试
Date date;
ZeroMemory(&date, sizeof(date));
date.nYear = 99;
date.nMonth = 12;
date.nMonthDay =31;
date.nWeekDay = 7;
cout << "sizeof(date)=" << sizeof(date) <<endl;
bitset<64> bs(*(unsigned __int64*)&date);
cout << "date=" << bs.to_string() << endl;
结果:
sizeof(date)=8
date=0000000000000000000011000110110000000000000000000000000011111111
其占8个字节,88,64位,故转(unsigned __int64*)指针。
特别注意中间0,是强制数据在下一个边界分配。




                                                   xx_player    2019.5


                                                      

现代C++的技巧-大浪淘金

           写东西比答题简单, 好弄。
   以上这些,虽然有些时日,仍是流行地。
   没看懂就参阅微软的msdn,有机器翻译成中文地,也有英文版地
   在里面找,还有很多没介绍地。我也不太懂,会被问地瞠目结舌地,毕竟那东西是微软,
   我只是搬运工而已,能搬出来就已经有成就感了。
   通过努力,你们再搬一些,你们就可以建高楼。
   代码编译在vs2015上测试通过。没有任何问题。






上一篇:软件启动项提示病毒木马
下一篇:数据库之本地数据库
16_avatar_middle
最佳答案
0 
在线会员 发表于 2019-5-7 23:48:32 | 显示全部楼层
标记一下,有空好好研究下
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )|网站地图wx_jqr

GMT+8, 2020-10-1 16:22

Powered by CcTry.CoM

© 2009-2020 cctry.com

快速回复 返回顶部 返回列表