emplace系列函数
先上一段常用的代码:
1 |
|
在这个过程中,我们的目的是为了产生一个对象数组,为了产生3个对象,调用了3*3次,这个过程执行过程:创建对象t调用构造函数—>调用对象t的拷贝构造函数放入集合—>调用析构函数。
Never underestimate your power to change yourself!
先上一段常用的代码:
1 | #include <iostream> |
在这个过程中,我们的目的是为了产生一个对象数组,为了产生3个对象,调用了3*3次,这个过程执行过程:创建对象t调用构造函数—>调用对象t的拷贝构造函数放入集合—>调用析构函数。
C++ 11之后才开始支持for-each语法。
示例:
1 | std::vector<std::string> v_str; |
for-each中的迭代器类型与数组或集合中的元素类型完全一致,而stl容器中的迭代器是类型的取地址类型即指针,因此对于上面的例子中,iter是string类型;如果用stl迭代器,那就是指向string的指针。
for-each对于复杂数据类型,迭代器是原始数据的拷贝,而不是引用,在这个过程中会额外调用构造函数的开销,必要的时候可以使用
auto& iter
而不是auto iter
这样就是原始数据的引用了。
假如我们有两个类point 和 Cpoint
现在我们需要用类point去构造Cpoint对象,一般实现方式是在Cpoint中定义如下构造:
Cpoint(point);
但有些情况下,这个构造是无法定义的:
- 用point的私有成员给Cpoint赋值(可以添加get方法解决),point没有定义Cpoint为友元类;
- 没有权限修改Cpoint,只能修改point;
这里我们可以在point重载Cpoint的构造函数:
1 | /* |
重载后,在需要point构造Cpoint时都会隐式的调用point中的重载构造函数
函数参数是以数据结构:栈的形式存取,从右至左入栈。
首先是参数的内存存放格式:参数存放在内存的堆栈段,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址。
理论上来说,只要获取到一个参数的地址,就可以通过地址偏移获取到其他参数的地址。
下面是<stdarg.h>里重要的几个宏定义:
typedef char* va_list;
void va_start(va_list ap, prev_param);
void va_arg(va_list ap, type);
将char 赋值给std::string如果不指定长度,则会默认以\0截断(ASCII码值为0);如果指定长度超过char 的长度,用std::cout系列的函数输出时,会把不属于char*之后的内存值打印出来,而对于printf系列的函数打印时,遇到\0会被截断,因而不能完全显示。这点在打印日志时,这类字符串需要注意。
如果是单个字符和一个字符串赋值给std::string 写法是有区别的:对于char,数目是第一个参数,对于char*,数目是第二个参数。
string(const char* s, size_t n);
string(size_t n, char c);
假定pstr是一个字符串,那么要写成string(pstr,n);如果pstr是一个字符,那么要写成string(n,pstr),而此时string(pstr, n)是一个错误的写法,可能会导致你的程序产生莫名其妙的问题,因为如果pstr是一个负值,负值转换成无符号整数size_t类型,n将非常大,会导致构造字符串时length非常大导致std::string 构造时抛出异常。