TokeyRoad

Never underestimate your power to change yourself!


  • 首页

  • 标签

  • 分类

  • 归档

stl容器新增的实用方法

发表于 2020-05-19 | 分类于 C++
字数统计: 1.1k | 阅读时长 ≈ 5

emplace系列函数

先上一段常用的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <list>
#include <vector>

class Test {
public:
Test(int a, int b) {
m_a = a;
m_b = b;
std::cout << "Test constructed" << std::endl;
}
~Test() {
std::cout << m_a << " Test destructed" << std::endl;
}

Test(const Test& t) {
if (this == &t) {
return;
}
this->m_a = t.m_a;
this->m_b = t.m_b;
std::cout << m_a << " Test copy-constructed" << std::endl;
}
private:
int m_a;
int m_b;
};

int main() {
std::vector<Test> vec;
vec.reserve(20);//,提前分好内存 避免vector的内存重分配
for (int i = 0; i < 3; ++i) {
Test t(i, i + 1);
vec.push_back(t);
}
system("pause");
return 0;
}
//output
Test constructed
0 Test copy-constructed
0 Test destructed
Test constructed
1 Test copy-constructed
1 Test destructed
Test constructed
2 Test copy-constructed
2 Test destructed

在这个过程中,我们的目的是为了产生一个对象数组,为了产生3个对象,调用了3*3次,这个过程执行过程:创建对象t调用构造函数—>调用对象t的拷贝构造函数放入集合—>调用析构函数。

阅读全文 »

foreach循环

发表于 2020-05-18 | 分类于 C++
字数统计: 474 | 阅读时长 ≈ 2

for-each

C++ 11之后才开始支持for-each语法。

示例:

1
2
3
4
5
6
7
8
std::vector<std::string> v_str;
v_str.push_back("aaa");
v_str.push_back("bbb");
v_str.push_back("ccc");
v_str.push_back("ddd");
for (auto iter : v_str) {
std::cout << iter.c_str() << std::endl;
}
注意
  1. for-each中的迭代器类型与数组或集合中的元素类型完全一致,而stl容器中的迭代器是类型的取地址类型即指针,因此对于上面的例子中,iter是string类型;如果用stl迭代器,那就是指向string的指针。

  2. for-each对于复杂数据类型,迭代器是原始数据的拷贝,而不是引用,在这个过程中会额外调用构造函数的开销,必要的时候可以使用auto& iter 而不是 auto iter 这样就是原始数据的引用了。

阅读全文 »

在一个类中重载另一个类的构造函数

发表于 2020-05-12 | 分类于 C++
字数统计: 359 | 阅读时长 ≈ 1
构造函数是一个特殊的操作符

假如我们有两个类point 和 Cpoint

现在我们需要用类point去构造Cpoint对象,一般实现方式是在Cpoint中定义如下构造:

Cpoint(point);

但有些情况下,这个构造是无法定义的:

  1. 用point的私有成员给Cpoint赋值(可以添加get方法解决),point没有定义Cpoint为友元类;
  2. 没有权限修改Cpoint,只能修改point;

这里我们可以在point重载Cpoint的构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
class Cpoint {
public:
Cpoint(int a) {
_p = a;
}
private:
int _p;
};
*/
class point {
public:
operator Cpoint() {
return Cpoint(_c_point);
}

private:
int _c_point;
};

重载后,在需要point构造Cpoint时都会隐式的调用point中的重载构造函数

阅读全文 »

可变参数 省略号的使用

发表于 2020-05-11 | 分类于 C++
字数统计: 418 | 阅读时长 ≈ 1

函数参数的传递原理

函数参数是以数据结构:栈的形式存取,从右至左入栈。

首先是参数的内存存放格式:参数存放在内存的堆栈段,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址。

理论上来说,只要获取到一个参数的地址,就可以通过地址偏移获取到其他参数的地址。

stdarg.h

下面是<stdarg.h>里重要的几个宏定义:

typedef char* va_list;

void va_start(va_list ap, prev_param);

void va_arg(va_list ap, type);

阅读全文 »

char*赋值给std::string的陷阱

发表于 2020-04-29 | 分类于 C++
字数统计: 294 | 阅读时长 ≈ 1
char*赋值给std::string的一些陷阱
  1. 将char 赋值给std::string如果不指定长度,则会默认以\0截断(ASCII码值为0);如果指定长度超过char 的长度,用std::cout系列的函数输出时,会把不属于char*之后的内存值打印出来,而对于printf系列的函数打印时,遇到\0会被截断,因而不能完全显示。这点在打印日志时,这类字符串需要注意。

  2. 如果是单个字符和一个字符串赋值给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 构造时抛出异常。

1…345…10
Tokey

Tokey

48 日志
9 分类
41 标签
  • C++8
  • Const1
  • Final1
  • HTTP2
  • Redis8
  • SDS1
  • STL4
  • TCP1
  • args1
  • atomic1
  • condition_variable1
  • construct1
  • foreach1
  • git2
  • go4
  • hexo1
  • json1
  • libcurl1
  • mutex1
  • operator1
  • override1
  • priority_queue1
  • shared_ptr1
  • stl1
  • unique_ptr1
  • vector1
  • 关键字2
  • 内存分配1
  • 列表对象1
  • 压缩列表2
  • 堆1
  • 字符串对象1
  • 指针和引用1
  • 敏捷开发1
  • 整数集合1
  • 栈1
  • 环境配置1
  • 缓存1
  • 设计模式1
  • 跳跃表1
  • 链表1
GitHub Google
Links
  • Hacker
本站已运行
© 2021 Tokey
博客全站共45.4k字
苏ICP备-20024031号
访问人数 总访问量 次
0%