c++Learning01

char和 w_char的区别

w_char是Unicode 字符的数据类型

1
typedef unsigned short wchar_t;

一般在在头文件中有这样的定义

1
typedef wchar_t WCHAR

为了让编译器识别 Unicode 字符串,需要在字符串前加上 L

1
wchar_t * a(L"china");

命名空间

命名空间的作用是解决变量,函数重名问题

没有命名的命名空间(匿名命名空间)可以直接使用,此时编译器会在内部为这个命名空间生成一个唯一的名字,而且还会自动生成一句 using 语句

1
2
3
4
5
namespce {
char c;
int i;
double d;
}

等价于

1
2
3
4
5
6
namespace __UNIQUE_NAME_ {
char c;
int i;
double d;
}
using namespace __UNIQUE_NAME_;

注意:命名空间都是具有external 连接属性的,只是匿名的命名空间产生的UNIQUE_NAME在别的文件中无法得到,这个唯一的名字是不可见的.
C++ 新的标准中提倡使用匿名命名空间,而不推荐使用static,因为static用在不同的地方,涵义不同,容易造成混淆.另外,static不能修饰class.

命名空间还可以使用别名

1
namespace a = mySpace;

命名空间可以使用嵌套,使用嵌套的命名空间时需要用到::操作符

命名空间可以拓展,用于软件的迭代式开发
一般不在命名空间中定义函数,而是声明一个函数指针,这个函数指针起到一个接口的作用
namespace 所有数据都是共有,不能加 private 修饰符,全是共有的

using 的作用域,从上往下,必须在命名空间的后方,

当 using 多个时,如果变量重名则命名空间冲突,会出现不明确错误.
命名空间如果在块语句内部using,则它的作用域在块结束后同时结束

###命名空间和全局变量的区别

c中全局变量可能会被局部变量屏蔽,在c++ 中可以使用::,”::”前面不加命名空间等价于取全局变量

函数重载是设计了委托,根据参数不同委托到不同的地址执行不同的函数

函数处理参数从右到左
默认参数放在右边,默认参数中间不允许加入不默认的,这样做是因为实参传给系统之后,系统会自左向右与形参进行匹配。如果函数时add(1,2),那么a=1,b=2,c等于多少呢?我们只有把参数全部传递过去之后,系统才能获得c的值,但这样做的话,为什么还要设置函数的默认参数呢?

所以编译系统不允许程序员这么做,因为这么做是毫无意义的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void printf(int c,int a = 5){
std::cout<<a<<endl;
}

void printf(int c){
std::cout<<c<<endl;
}
int main(){
// printf(6);
//此时会有歧义,所以要用函数指针调用
void (*p1)(int c, int a) = printf;
// void (*p2)(int c) = printf;
// void (*pp)(int c) = printf;
p1(6,7);
//参数需要补全,函数指针没有默认参数,需要全部输入数据,如果想使用默认参数特性最好使用命名空间去解决这个问题
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
void printf(int c,int a = 5){
std::cout<<a<<endl;
}

void printf(double c){
std::cout<<c<<endl;
}
int main(){
printf(6);
return 0;
}

这种情况下不冲突,如果需要输入的参数类型不一样,数目不一样,顺序不一样,则不会出现冲突

1
一个引用符引用左值,两个引用符引用右值
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
int& getA(){
int a = 10;//a在栈上,
int&ra = a;
return ra;
}
int main(){
int & ra = getA();
std::cout<<ra<<endl;
std::cout<<"hello"<<endl;
std::cout<<ra<<endl;
/*
* 10
* hello
* 32767
* */
return 1;
}

int* & getA(){
int * p = new int(5);
int * &rp = p;
return rp;
}
//返回引用指针
int main(){
int *& ra = getA();
// int *p = ra;使用一个变量接着,
int * p1 = ra;


std::cout<<*ra<<endl;
std::cout<<*p1<<endl;
std::cout<<"hello"<<endl;
// delete (p1);
std::cout<<*p1<<endl;
std::cout<<*ra<<endl;
//c++删除内存后禁止访问,而且指针
delete(*p1);
std::cout<<p1<<endl;
std::cout<<*p1<<endl;
std::cout<<*ra<<endl;
/*
* 10
* hello
* 32767
* */
return 1;
}

在栈上面的内存会在函数调用完就清除掉

1
2
3
4
5
6
7
8
9
10
//const
//c语言中const 变量可以被指针间接改变
int main() {
const int num = 5;
int *p = &num;
*p = 3;

printf("%d\n",*p);
return 0;
}

c++中不行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(){
const int num = 5;
int *p = (int *)&num;
*p = 2;
std::cout<<num<<endl;
}
//所得结果仍然是5,因为int *p = (int *)&num;()强转是C语言的转换方式
//虽然编译成功但是c++不会执行这段代码?还是执行了但是维护了一个常量表,通过 VS 反编译看看吧
int main(){
const int num = 5;
int *p = const_cast<int*>(&num);
*p = 2;//编译通过,但是貌似并没有起作用
std::cout<<num<<endl;
}
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
int main(){
int a = 10;
const int b =5;
// int const * p1(&a);//经常使用这种形式,用于限定权限(所以不会严格的检查类型),只能读不能写,所以可以操作
// const int * p2(&a);
// *p1 = 3;
// *p2 = 6;
// const在*左边,指向常量的指针变量,常量指针,不能改变指向的值
int * const p1(&a);
//指向变量的指针
int * const p2(&b);//cannot initialize a variable of type 'int *const' with an rvalue of type 'const int *'
//&b是 const int * p2是一个指向变量的指针常量

// const int * p2;
//
// int * const pp;
// const int const * p3;


}

int select(const int &rum){
// rum--;
return rum;
}


int main(){
const int num1 =10;
int num2 = 20;
std::cout<<select(num2)<<endl;
return 1;
}

//真实的内存已经被修改,从常量表里获取了值
//const 编译器会优化,不会从内存读取
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
 int main(){
//不能 delete两次

// int a[10];
// int * p = a;
// int i = 0 ;
// for (auto date:p){
//
// }
int *p = new int[10];
int i = 0;
for (int j = 0; j < 10; ++j) {
std::cout<<p[j]<<endl;
}
std::cout<<endl;
for (int j = 0; j < 10; ++j) {
p[j] = i++;
std::cout<<p[j]<<endl;
}
std::cout<<endl;
std::cout<<p<<endl;
delete []p;//删除数组的空间,基本数据类型可以直接 delete, 复杂类型必须[]
std::cout<<p<<endl;
// for (int j = 0; j < 10; ++j) {
// std::cout<<p[j]<<endl;
// }

return 1;
}
1
2
3
4
5
6
7
8
int main(){
int *p = new int[80];
int (*px) [10] = (int (*) [10])p;
//new只能分配线性

// px[i][j];
return 1;
}

删除数组的空间,基本数据类型可以直接 delete, 复杂类型必须[]