c++ 学习笔记
c++ 学习中记录下来的一些要点,方便以后复习。
1. 变量定义的时候,多使用 auto 关键字。
auto x = (uint8_t)y.x
2. 很多宏定义都可以使用 constexpr 来代替,有很多好处。唯一需要宏定义的地方是预处理。
参考:https://stackoverflow.com/questions/42388077/constexpr-vs-macros
3. #include 可以用 #include 来代替。
4. format string is not a string literal(potentially insecure) 这个警告是在不定参数的函数调用中会出现,起因是编译器没有那么智能。
所以对于类似于 char str[] = "xyz"; log(str) 这样的调用就会报错,有两种解决方法:
- 显式的写出来 log("xyz")
- 增加第二个参数 log(str, nullptr)。
5. strcat 用于把一个字符串追加到另外一个字符数组里面。
6. snprintf 这个库函数在最后一个位置上面填充 '\0'。
参考: https://www.runoob.com/cprogramming/c-function-snprintf.html
7. json 解析
char strBuf[]="{ \"id\":666, \"name\":\"henryHe\", }";
std::istringstream iss(strBuf); ////必须得强制类型转换
Json::Value readValue;
Json::CharReaderBuilder rbuilder;
rbuilder["collectComments"] = false;
std::string errs;
bool ok = Json::parseFromStream(rbuilder, iss , &readValue, &errs);
cout <<"ok: "<<ok<<endl;
cout <<"id: "<<readValue["id"]<<endl;
std::string name = readValue["name"].asString();
int id= readValue["id"].asInt();
cout <<"name: "<<readValue["name"]<<endl;
参考: https://www.cnblogs.com/music-liang/p/12904554.html https://www.cnblogs.com/esCharacter/p/7657676.html https://blog.csdn.net/centnetHY/article/details/83309796
8. curl,设置 CURLOPT_POSTFIELDS,设置HTTP请求body内容,CURLOPT_POSTFIELDSIZE设置body大小,如果body内容是以\0结尾,可以不指定body大小。
参考: https://cloud.tencent.com/developer/article/1580392
9. 显示时间
size_t strftime (char* ptr, size_t maxsize, const char* format,
const struct tm* timeptr );
ptr:存储转换结果
maxsize:复制到ptr的最大字符数,包括结束符'\0'
format:转换格式,类似printf,可加入其他需要复制过去的字符
timeptr:时间
char buf[20];
tm* local_time = std::localtime(&t);
strftime(buf,sizeof(buf),"%F %X",local_time);
参考: https://blog.csdn.net/qq_34645629/article/details/84783092 https://stackoverflow.com/questions/6124768/how-to-get-local-time-and-put-it-in-a-string
10. 如果一个类需要放到 vector 中,进行排序,可以在这个类里面进行 运算符重载,然后再需要用的时候,使用 less 或者 greater 之类的函数,注意使用 less, greater 需要
include <functional>
class DetectDetail
{
public:
std::string mName = "";
int32_t mScore = 0;
cv::Rect2i mRectBox = cv::Rect2i(0, 0, 0, 0);
cv::Rect2i mLabelBox = cv::Rect2i(0, 0, 0, 0);
std::string mLabel = "";
cv::Point2i mLabelPos = cv::Point2i(0, 0);
std::string mPosition = "";
bool operator<(const DetectDetail &d) const
{
if (this->mScore < d.mScore)
return true;
else
return false;
}
bool operator>(const DetectDetail &d) const
{
if (this->mScore > d.mScore)
return true;
else
return false;
}
};
#include <functional>
{
vector<DetectDetail> test;
DetectDetail tmpD;
tmpD.mName = "t1";
tmpD.mScore = 10;
test.push_back(tmpD);
tmpD.mName = "t2";
tmpD.mScore = 20;
test.push_back(tmpD);
std::cout << test[0].mName << ", " << test[1].mName << std::endl;
// 正序
sort(test.begin(), test.end(), less<DetectDetail>());
std::cout << test[0].mName << ", " << test[1].mName << std::endl;
// 倒序
sort(test.begin(), test.end(), greater<DetectDetail>());
std::cout << test[0].mName << ", " << test[1].mName << std::endl;
}
参考: https://blog.csdn.net/luofengmacheng/article/details/17259659 https://blog.csdn.net/weixin_41588502/article/details/86620305 http://c.biancheng.net/view/520.html https://blog.csdn.net/qq_42835910/article/details/86774324 https://www.cnblogs.com/lengbingshy/p/3491192.html
11. undefined reference to static class member 在链接的时候,找不到静态成员变量。解决的方法是在 h 头文件中申明静态成员变量,在cpp 文件的源代码中定义静态成员变量,需要注意的是,定义不能再任何函数里面,包括不能再构造函数里面,只能类似于全局变量那种定义的样子。 而且静态成员变量好像不能用 private 来修饰。
参考: https://blog.csdn.net/XSHSZJU216/article/details/44465073
https://blog.csdn.net/fengfengdiandia/article/details/82465987
12. 字符串比较
string 可以用 "==" 或者 string::compare 比较。 字符数组 可以用 strcmp 来比较。
参考: https://blog.csdn.net/zcc1229936385/article/details/79747371 https://blog.csdn.net/ljl1015ljl/article/details/86557512 https://blog.csdn.net/leek5533/article/details/105950109
13. 多线程,c++11 后,有 thread 库可以使用,如果是在线程绑定的是类的成员函数,那么注意需要增加第二个参数,指向这个类的实例。
#include <thread>
#include <iostream>
class Greet
{
const char *owner = "Greet";
public:
void SayHello(const char *name) {
std::cout << "Hello " << name << " from " << this->owner << std::endl;
}
};
int main() {
Greet greet;
std::thread thread(&Greet::SayHello, &greet, "C++11");
thread.join();
return 0;
}
上面如果线程是在类里面创建的,那么需要这样用: std::thread thread(&Greet::SayHello, this, "C++11");
参考: https://www.jianshu.com/p/dcce068ee32b
14. 查看 key 是否存在 map 中。
if (mymap.find(key) == mymap.end())
cout << "没有这个key" << endl;
参考: https://blog.csdn.net/Leo_csdn_/article/details/85066264
15. 获取 vector 的大小
vec.size()
16. c++ 11, 14, 17 特性
参考: https://blog.csdn.net/mc18740458059/article/details/107327243
17. 如何确定 gcc 支持的 c++ 版本。man g++
搜索 -std=
查找 c++ 版本,或者直接 g++ --version
查找到 g++ 版本,然后去相关网站搜索。
参考: https://blog.csdn.net/tusong86/article/details/105678201
18. cout 打印指针地址,会直接自动打出整个数据。如果想要只打印地址,那么就需要把指针转为空指针,就可以。
cout << "字符串起始地址值: " << static_cast<const void *>(pszStr) << endl;
参考: https://www.cnblogs.com/wxxweb/archive/2011/05/20/2052256.html
19. 读写二进制文件
int main()
{
CStudent s;
ofstream outFile("students.dat", ios::out | ios::binary);
while (cin >> s.szName >> s.age)
outFile.write((char*)&s, sizeof(s));
outFile.close();
return 0;
}
int main()
{
CStudent s;
ifstream inFile("students.dat",ios::in|ios::binary); //二进制读方式打开
if(!inFile) {
cout << "error" <<endl;
return 0;
}
while(inFile.read((char *)&s, sizeof(s))) { //一直读到文件结束
int readedBytes = inFile.gcount(); //看刚才读了多少字节
cout << s.szName << " " << s.age << endl;
}
inFile.close();
return 0;
}
参考: http://c.biancheng.net/view/302.html https://blog.csdn.net/lightlater/article/details/6364931
20. 二维指针
float * boxes;
float (*p)[4] = (float(*)[4])boxes;
cout << p[0][0] << p[0][1] << p[0][2] << p[0][3] << endl;
参考: http://c.biancheng.net/view/2022.html
21. 格式化字符串
#include <sstream>
using std::stringstream;
// 准备根据格式造字符串流
stringstream fmt; /* 或者使用 ostringstream */
// 造字符串流
fmt << "test string: " << haha << ". test number: " << num;
// 获取最终需要的字符串
string targetString = fmt.str();
参考: https://blog.csdn.net/qq_29695701/article/details/99059536
22. error: default argument given for parameter 。 默认参数只能在申明或者定义中出现一次。一般建议在申明中用默认参数,定义的时候不用。
参考: https://blog.csdn.net/david_xtd/article/details/9704685
23. error: cannot declare member function ‘static ’ to have static linkage。 静态成员函数只能在申明的时候用 static,不能再定义的时候用。
参考: https://blog.csdn.net/guoxiaojie_415/article/details/5364354
24. mutex的 lock 是阻塞的,try_lock 是非阻塞的。
参考: https://blog.csdn.net/zx3517288/article/details/52743011
25. 可以使用 mutex , 也可以使用 lock_guard 或者 unique_lock。
参考: https://www.cnblogs.com/xudong-bupt/p/9194394.html https://www.jianshu.com/p/118aba1b88f1 https://www.cnblogs.com/Asp1rant/p/12420769.html https://www.cnblogs.com/long5683/p/12997011.html
26. segment fault 时,可以选用的工具是: catchsegv,最简单的用法如下:
catchsegv ./test
参考: https://www.cnblogs.com/wahaha02/p/8034112.html https://tinylab-1.gitbook.io/cbook/02-chapter9#toc_7140_15195_7 https://blog.csdn.net/hccloud/article/details/51548274 https://www.cnblogs.com/wpgraceii/p/10622582.html https://blog.csdn.net/u010150046/article/details/77775114 https://www.jianshu.com/p/66e9bc3b4988
27. 读写文本文件
ifstream inFile(LABEL_FILE, ios::in);
if (!inFile.is_open())
{
cerr << "Error: open labels" << endl;
return -1;
}
string s ="";
while (inFile >> s) // or while (getline(inFile, s))
{
mLabels.push_back(s);
cout << "label: " << s << endl;
}
参考: https://cloud.tencent.com/developer/article/1403612
28. 获取命令行参数,长参数,使用 getopt_long_only(),短参数,使用 getopt
int opt;
int optionIndex = 0;
const char *optString = "anpu";
static struct option longOptions[] =
{
{"all", no_argument, NULL, 'A'},
{"nfc", no_argument, NULL, 'N'},
{"pir", no_argument, NULL, 'P'},
{"usr", no_argument, NULL, 'U'},
{0, 0, 0, 0}
};
while ((opt = getopt_long_only(argc, argv, optString, longOptions,
&optionIndex)) != -1)
{
cout << "opt: " << opt << endl;
cout << "optind: " << optind << endl;
cout << "option index: " << optionIndex << endl;
cout << argv[0] << ", " << argv[1] << endl;
cout << endl;
}
参考: https://blog.csdn.net/qq_34719188/article/details/83788199 https://blog.csdn.net/zengraoli/article/details/19612627
29. 遍历 map
for (auto p : digitronMap)
{
if (p.first == c)
return p.second;
}
参考: https://blog.csdn.net/xiong_min/article/details/87859214
30. mq 错误打印
gPirEventSend = mq_open("/pir_event", O_WRONLY | O_CREAT | O_NONBLOCK, 0666, &attr);
if (gPirEventSend == -1)
{
cerr << "pir event queue send open error:" << strerror(errno) << endl;
mq_close(gPirEventSend);
}
参考: https://blog.csdn.net/mayue_web/article/details/92712163
31. const 内含是文件内使用,和 extern 搭配,容易出问题。 extern const 少用。详见
https://blog.csdn.net/audio_algorithm/article/details/79420067
32. 实现发布订阅模式。
参考: http://www.cs.sjsu.edu/faculty/pearce/modules/patterns/events/pubsubimp.htm https://blog.csdn.net/qq_35865125/article/details/88322729?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=57fa85e0-9ef9-45d3-96dc-1c3dc6422674&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control https://blog.csdn.net/u011040361/article/details/45308855
33. variable 'std:ofstream' has initializer but incomplete type 错误。
这个保存只要增加头文件 #include <fstream>
即可。
参考: https://blog.csdn.net/whyrun/article/details/7425003
34. 一次性读取文本文件有两种方法
第一种方法:
#include <string>
#include <fstream>
#include <streambuf>
std::ifstream t("file.txt");
std::string str((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
注意: std::istreambuf_iterator<char>(t)
这两边必须加括号,否则结果就不对。
第二种方法:
#include <string>
#include <fstream>
#include <sstream>
std::ifstream t("file.txt");
std::stringstream buffer;
buffer << t.rdbuf();
std::string contents(buffer.str());
参考: https://blog.csdn.net/tulip527/article/details/7976471 https://blog.csdn.net/da_kao_la/article/details/85164427 https://blog.csdn.net/vinson0526/article/details/50829627
35. 字符串和字符数组互相转换
char ch [] = "ABCDEFG";
string str(ch);//也可string str = ch;
或者
string str;
str = ch;//在原有基础上添加可以用str += ch;
char ch[10];
ch = s.c_str();
参考: https://www.cnblogs.com/fnlingnzb-learner/p/6369234.html
36. 使用typeid().name()
输出变量类型
cout<<typeid(a).name()<<endl;
参考: https://blog.csdn.net/weixin_41770786/article/details/107461573 https://blog.csdn.net/weixin_34074740/article/details/91736705
37. vector 打印
template<typename T>
std::ostream & operator<<(std::ostream & os, std::vector<T> vec)
{
os<<"{";
if(vec.size()!=0)
{
std::copy(vec.begin(), vec.end()-1, std::ostream_iterator<T>(os,""));
os<<vec.back();
}
os<<"}";
return os;
}
#include <iterator> // for std::ostream_iterator
#include <algorithm> // for std::copy
template <typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
if (!v.empty()) {
out << '[';
std::copy(v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
out << "\b\b]";
}
return out;
}
参考: https://www.codenong.com/15435313/ https://www.jianshu.com/p/8f25c7e03085
38. transform 只是使用指定的函数对参数进行操作, accumulate 还额外有保存处理数据结果作为下次参数的功能。
参考: https://blog.csdn.net/oMuYeJingFeng1/article/details/26148903 https://blog.csdn.net/fengbingchun/article/details/63252470 https://blog.csdn.net/u011499425/article/details/52756242 https://www.cnblogs.com/mtcnn/p/9423646.html