@The Cherno C++ Series ( p31 - p35 )
C++ Series
Array
- 栈上创建数组
int example[5];
int* ptr = example;
//赋值的不同表达方式
example[2] = 6;
*(ptr + 2) = 6;
*((int*)(char*)ptr + 8) = 6;
//偏移多少取决于指针类型
- 堆上创建数组
int* another = new int[5];
another[2] = 6;
delete[] another;
这种方式存在内存间接寻址,如果要访问数组成员,就会在内存中跳跃,可能会影响性能。应该选择栈上创建数组来避免。
- C++11中有std :: array 有很多优点,边界检查、获取数组大小等;
在堆上创建数组没有办法知道数组大小,也有但不可靠;
在栈上创建可以通过知道数组大小。
//std
std::array<int,5> another;
another.size();
//栈上创建数组
//方法1
int a[5];
int count = sizeof(a) / sizeof(int);
//方法2
//example_size 必须固定不变
static const int example_size = 5;
int example[example_size];
String
std::string 构造函数接受 参数const char或 char
#include <iostream>
#include <string>
//方法1
std::string name = "cherno";
name += "hello";
//方法2
std::string name = std::string("cherno") + "hello";
bool contains = name.find("no") != std::string::npos;
std::cout << name << std::endl;
//在函数中传递string, 这里相当于copy string,在heap上动态分配一个新的字符数组; string copy 其实很慢,so可以用引用
//这里有一点点疑问?不应该是在栈上吗?
//string类 有一个私有成员char* 在栈上,记录堆上分配内存的地址,实际数据是储存在堆上的。
void printString(std::string string)
{
string += 'h';
std::cout << string <<std::endl;
}
//引用 + const 承诺不修改
void printString(const std::string& string)
{
std::cout << string <<std::endl;
}
string literals
- 字符串的结束 ‘\0’
- 一些使用
char *name = "cherno";
name[2] = 'a'; // error
char name[] = "cherno";
name[2] = 'a'; // right
//C++11中 clang编译器只会让你编译 const char*
char *name = (char*)"charno";
//宽字符
const wchar_t *name2 = L"Cherno";
//具体占几个字节是由编译器决定的 windows 2字节 linux 4字节 mac 4字节,所以是一个变动的值,如果确定要2字节,可以定义char16_t
//不同类型的字符
const char16_t *name3 = u"Cherno";
const char16_t *name4 = U"Cherno";
const char* name = u8"Cherno";
//C++14中 提供了一些方法append
using namespace std::string_literals;
//方法1
std::string name0 = "cherno"s + "hello";
//方法2
//R忽略转义字符
const char* example = R"(line1
line2
line3
line4)";
//方法3
const char* ex = "line1"
"line2"
"line3";
//类型
std::wstring name1 = L"Charno"s + L"hello";
//u32string
- 内存:string literals 永远只在只读区域。
Const
- 包含常量和只读两层含义
- const int* a :不能修改a指针指向的内容,可以指向别的东西,等同于int const* a。
- int* const a:与上面的相反,可以改变指针指向的内容,但是不能指向别的东西。
- const int* const a:都不能改变。
- const在类中的使用
class Entity
{
private:
int m_X, m_Y;
public:
//这个方法不会修改类成员变量,只能读
int GetX() const
{
return m_X;
}
int GetX()
{
return m_X;
}
void SetX(int x)
{
m_X = x;
}
};
void PrintEntity(const Entity& e)
{
//这里是调用const方法
std::cout << e.GetX() << std::endl;
}
class Entity
{
private:
int* m_X, m_Y; //这里注意 m_X是指针 m_Y是int
//int* m_X, *m_Y; //两个都是指针
public:
//这个方法不能改变实际的Entity类
//包括指针本身以及指针所指的内容
const int* const GetX() const
{
retun m_X;
}
}
mutable
- 如果const方法要修改成员变量,那就标记为mutable (90%使用场景)
class Entity
{
private:
int m_X, m_Y;
mutable int z;
public:
//这个方法不会修改类成员变量,只能读
int GetX() const
{
z = 2;
return m_X;
}
int GetX()
{
return m_X;
}
};
- 运用在lambda表达式中(很少用,几乎无)
int main()
{
int x = 8;
//lambda一次性小函数
//auto f = [=]() //只是传值
//auto f = [&]()
//auto f = [&x]()
//auto f = [x]()
auto f = [=]()
{
int y = x;
y++;
std::cout << y << std::endl;
std::cout << "hello" << std::endl;
};
等同于>>>>>>>
auto f = [=]() mutable
{
x++;
std::cout << x << std::endl;
std::cout << "hello" << std::endl;
};
f();
std::cout << x << std::endl;
//这里控制台的显示是分别是 9 hello 8
//说明mutable在lambda中只是复制的8
}