C++记录(一)
1
extern 符表示该变量不是当前作用域定义的,用于声明。
如extern i;表示i不是当前作用域里的,是其他某个include的cpp文件里的变量。
2
int *p=0;相当于初始化p为空指针。
3
指针是对象,引用不是对象。所以可以取指针的指针或者指针的引用,但不可以取引用的指针。
指针一定要指向对象。
4
const int x=1;
const int *p=&x; //p为指向常量的指针
int * const q=&x; //q为常量指针,即q只能指向x,不能更改为指向其他变量
没有int & const p;这种写法
5
typedef int* p; //命名int*为p,即p x;等同于int *x;
const 修饰typedef的新类型名时,const优先与新类型名结合,如const p *x;表示(const p) * x,即常量
6
可以利用auto &c:s遍历字符串s中的每个元素,并且c是作为引用指向对应的元素的,可以用来遍历修改s中的某些元素,如下修改s中字母为大写。
// #include <stdio.h>
#include <iostream>
#include <string>
#include <cctype>
// #include <string.h>
// #include <cstring>
// using std::cin;
// using std::cout;
using namespace std;
int main()
{
string s="fewqfqdwqteqwghrte";
for(auto &c:s)
{
c=toupper(c);
}
cout<<s;
system("pause");
return 0;
}
7
->完全等价于先解引用再.操作,如下:
int main()
{
string s("412343141");
string *t=&s;
cout<<(*t).empty();
cout<<t->empty();
getchar();
}
之前一直以为只有是类的指针取类里的子数据才能用->符号,今天学习了
8
i++相当于int temp=i;i+=1;i=temp;三个语句,返回右值
++i只有自增一步,并且返回左值
9
a&(-a)截取a的二进制位最后一位为1的数字,如a=10100,a&(-a)等于00100
a&(a-1)删除a的为1的最右侧位。
10
顶层const即变量本身为常量,底层const是变量(指针、引用)指向的是常量。
11
int转string std::to_string,该函数不光可以转整数,所有无符号、long、long long、单双精度浮点数都可以。
string转int stoi()
char * 转int atoi()
另外可以用sprintf将多个元素用指定的格式写入字符串(和printf函数类似,只是后者写到屏幕,前者写入字符串),返回写入的字符数
eg:
int main()
{
char s[14];
cout<<sprintf(s,"%d,%.1f",1,2.5)<<endl;
cout<<s;
getchar();
return 0;
}
输出:
同理sscanf可以将某字符串内容以指定格式分割写入多个变量
一篇讲sscanf的博客
还可以用stringstream,这个比较慢一般不用。
eg:
int main()
{
stringstream ss;
string s;
ss<<124;
ss>>s;
cout<<s;
getchar();
return 0;
}
12
explicit用来防止类的构造函数的隐式转换。
例子如下:
新一点的c++如vs2019里不用编译就会报错。
class Test1
{
public:
Test1(int n)
{
num=n;
}//普通构造函数
private:
int num;
};
class Test2
{
public:
explicit Test2(int n)
{
num=n;
}//explicit(显式)构造函数
private:
int num;
};
int main()
{
Test1 t1='a';//隐式调用其默认拷贝构造函数,成功
Test2 t2=12;//编译错误,不能隐式调用其构造函数
Test2 t2(12);//显式调用成功
return 0;
}
13
static修饰局部变量生成局部静态对象。在第一次经过时初始化,之后一直存留在全局变量区。即在函数中第一次遇到该语句,初始化整个变量,但依然还是局部变量(其他函数中不可见),但若再次进入当前函数,不再执行初始化语句,而是直接使用之前保存好的值。
#include <stdio.h>
void test()
{
static int num = 0;
num++;
printf("%d ", num);
}
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
test();
}
return 0;
}
14
initializer_list可以传入不定个形参,但一定是同一类型的,类型要指定好,如下面这样。
int f(initializer_list<int> p)
{
for (auto x : p)
{
cout << x << endl;
}
return 0;
}
15
inline函数(内联函数)是为了替换宏函数来的,更加安全。inline关键字应该在函数定义的时候加,声明的时候加inline是没有用的。
关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。
16
class、struct占用的空间一定是成员变量最大类型长度的整数倍(数据对齐)
如下面:
A类a占0号字节,空一格,b占2~3,c占4 ~7,d占8 ~15,总占用0 ~15,16个字节。
B类b占0 ~3,空四格4 ~7(四个字节),a占8 ~15,c16 ~17,d18,目前总长度19,但B中最大变量double长度8个字节,而82=16,83=24,故还要填24-19=5个字节。
17
C++容器的size函数返回的都是size_t类型,这个类型是unsigned int,简单的int siz=s.size()。比如在for循环里这样写:
for(int i=0;i<s.size()-1;++i)
{
当s为空时,s.size()-1的值为ffffffff,表示4294967295,而不是我们想要的-1。
这种情况for会进入循环,这不是我们想要的。
所以解决办法:为空提前单独判断
18