目录
https://www.cnblogs.com/clover-toeic/p/3737011.html
该对函数是strcpy/strcat调用的“安全”版本,但仍存在一些问题:
sprintf使用控制字符串来指定输出格式,该字符串通常包括”%s”(字符串输出)。若指定字符串输出的精确指定符,则可通过指定输出的最大长度来防止缓冲区溢出(如%.10s将复制不超过10个字符)。也可以使用”“作为精确指定符(如”%.s”),这样就可传入一个最大长度值。精确字段仅指定一个参数的最大长度,但缓冲区需要针对组合起来的数据的最大尺寸调整大小。
“字段宽度”(如”%10s”,无点号)仅指定最小长度——而非最大长度,从而留下缓冲区溢出隐患。
参考https://www.cnblogs.com/52php/p/5724390.html
int snprintf(char *restrict buf, size_t n, const char * restrict format, ...);
函数说明:最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个 '\0'
。所以如果目标串的大小为 n 的话,将不会溢出。
函数返回值:若成功则返回欲写入的字符串长度(而不是实际写入的字符串度),若出错则返回负值。
用法:
char str[10] = {0,};
snprintf(str, sizeof(str), "0123456789012345678");
printf("str=%s\n", str);
https://blog.csdn.net/ljp1919/article/details/50463761
效率上:
内存空间占用上:
所以,在效率和内存占用上面,boost::unordered_map 都更具有优势。
https://blog.csdn.net/weixin_40081916/article/details/79377564
auto_ptr是用于C++11之前的智能指针。由于 auto_ptr 基于排他所有权模式:两个指针不能指向同一个资源,复制或赋值都会改变资源的所有权。auto_ptr 主要有两大问题:
unique_ptr特性
unique_ptr可以:
unique_ptr十分依赖于右值引用和移动语义。
在C++11中已经放弃auto_ptr转而推荐使用unique_ptr和shared_ptr。unique跟auto_ptr类似同样只能有一个智能指针对象指向某块内存,但它还有些其他特性。unique_ptr对auto_ptr的改进如下:
auto_ptr通过拷贝构造或者operator=赋值后,对象所有权转移到新的auto_ptr中去了,原来的auto_ptr对象就不再有效,这点不符合人的直觉。unique_ptr则直接禁止了拷贝构造与赋值操作。
unique_ptr像上面这样一般意义上的复制构造和赋值或出错,但在函数中作为返回值却可以用
我们知道auto_ptr不可做为容器元素,会导致编译错误。虽然unique_ptr同样不能直接做为容器元素,但可以通过move语义实现。
unique_ptr持有对对象的独有权,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。
unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。
离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。
类似shared_ptr,用unique_ptr管理非new对象、没有析构函数的类时,需要向unique_ptr传递一个删除器。不同的是,unique_ptr管理删除器的方式,我们必须在尖括号中unique_ptr指向类型后面提供删除器的类型,在创建或reset一个这种unique_ptr对象时,必须提供一个相同类型的可调用对象(删除器),这个删除器接受一个T*参数。
unique_ptr不允许两个独占指针指向同一个对象,在没有裸指针的情况下,我们只能用release获取内存的地址,同时放弃对对象的所有权,这样就有效避免了多个独占指针同时指向一个对象。 而使用裸指针就很容易打破这一点。
在调用u.release()时是不会释放u所指的内存的,这时返回值就是对这块内存的唯一索引,如果没有使用这个返回值释放内存或是保存起来,这块内存就泄漏了。
https://blog.csdn.net/qq_33266987/article/details/78784286
shared_ptr允许多个该智能指针共享地“拥有”同一堆分配对象的内存,这通过引用计数(reference counting)实现,会记录有多少个shared_ptr共同指向一个对象,一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。
shared_ptr的额外开销:
使用:
可以使用模板函数 make_shared 创建对象, make_shared 需指定类型(‘<>’中)及参数(‘()’内), 传递的参数必须与指定的类型的构造函数匹配:
std::shared_ptr<int> sp1 = std::make_shared<int>(10);
std::shared_ptr<std::string> sp2 = std::make_shared<std::string>("Hello c++");
也可以定义 auto 类型的变量来保存 make_shared 的结果。
auto sp3 = std::make_shared<int>(11);
printf("sp3=%d\n", *sp3);
auto sp4 = std::make_shared<std::string>("C++11");
printf("sp4=%s\n", (*sp4).c_str());
成员函数:
shared_ptr是线程安全的,但get函数不是:
https://www.zhihu.com/question/56836057
https://www.cnblogs.com/lsgxeva/p/7788061.html
https://www.cnblogs.com/diysoul/p/5930361.html
当做函数返回值的时候,返回值就好,不要返回引用 !!!!
https://stackoverflow.com/questions/24440613/c-how-to-return-a-shared-ptr-from-function
weak_ptr是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,它可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用计数的增加或减少。没有重载 * 和 -> 但可以使用lock获得一个可用的shared_ptr对象
weak_ptr的使用更为复杂一点,它可以指向shared_ptr指针指向的对象内存,却并不拥有该内存,而使用weak_ptr成员lock,则可返回其指向内存的一个share_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr。
小结一下:
https://www.cnblogs.com/wangguchangqing/p/6134635.html
参考https://www.cnblogs.com/pop-lar/p/5123014.html
thread_local变量是C++ 11新引入的一种存储类型。它会影响变量的存储周期(Storage duration),C++中有4种存储周期:
有且只有thread_local关键字修饰的变量具有线程周期(thread duration),这些变量(或者说对象)在线程开始的时候被生成(allocated),在线程结束的时候被销毁(deallocated)。并且每 一个线程都拥有一个独立的变量实例(Each thread has its own instance of the object)。thread_local 可以和static 与 extern关键字联合使用,这将影响变量的链接属性(to adjust linkage)。
那么,哪些变量可以被声明为thread_local?以下3类都是ok的
既然每个线程都拥有一份独立的thread_local变量,那么就有2个问题需要考虑:
http://zh.cppreference.com/w/cpp/atomic/atomic
https://www.2cto.com/kf/201706/649733.html
C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为。通常的做法是在修改共享数据成员的时候进行加锁–mutex。在使用锁的时候通常是在对共享数据进行修改之前进行lock操作,在写完之后再进行unlock操作,经常会出现由于疏忽,导致由于lock之后,在离开共享成员操作区域时忘记unlock,导致死锁。
针对以上的问题,C++11中引入了std::unique_lock与std::lock_guard两种数据结构。通过对lock和unlock进行一次薄的封装,实现自动unlock的功能。
https://segmentfault.com/a/1190000006812825
例如:
struct A {
std::vector<int> xx;
std::unordered_map<std::string, int> aa;
};
std::vector<A> m;
A tmp;
tmp.xx.emplace_back(2);
tmp.xx.emplace_back(4);
tmp.seconds_pass=3;
tmp.aa.insert(std::make_pair("test1", 2));
tmp.aa.insert(std::make_pair("test2", 288));
m.emplace_back(tmp);
// ...
// sort的时候会涉及大量拷贝
std::sort(m.begin(), m.end(),
[](A a, A b) {
return a.seconds_pass < b.seconds_pass;
});
可以改成
struct A {
std::vector<int> xx;
std::unordered_map<std::string, int> aa;
int seconds_pass;
};
typedef std::shared_ptr<A> APtr;
std::vector<APtr> m;
APtr tmp = std::make_shared<A>();
tmp->xx.emplace_back(2);
tmp->xx.emplace_back(4);
tmp->seconds_pass=3;
tmp->aa.insert(std::make_pair("test1", 2));
tmp->aa.insert(std::make_pair("test2", 288));
m.emplace_back(tmp);
// ...
std::sort(m.begin(), m.end(),
[](APtr a, APtr b) {
return a->seconds_pass < b->seconds_pass;
});
参考https://stackoverflow.com/questions/66230707/c-builtin-functions-source-codes
https://github.com/gcc-mirror/gcc/blob/master/gcc/builtins.def#L317
例如__builtin_strlen
函数就是
DEF_LIB_BUILTIN (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
在厂内的话,就是/opt/compiler/gcc-8.2/lib64/gcc/x86_64-pc-linux-gnu/8.2.0/plugin/include/builtins.def
中
DEF_LIB_BUILTIN_CHKP (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)