1. namespace
1.1 namespace的价值和定义
在c++中存在着大量的类,这些变量函数,类都存在全局变量当中为了,避免命名冲突c++当中引入了namespace。
在命名冲突中c语言也是普遍存在的观察如下c代码:
#include<stdio.h>
#include<stdlib.h>
int rand = 12;
int main()
{
printf("%d",rand);
}
在运行时会报的错误
当引入namespace时即可有效的避免此类问题,如下c++代码
#include<stdio.h>
#include<stdlib.h>
namespace a
{
int rand = 12;
int add(int x, int y)
{
return x + y;
}
struct b
{
int val;
int* next;
};
}
int main()
{
printf("%d", a:: rand);
}
namespace的使用与c语言当中的结构体的使用类似,但与c语言结构体不同的是nmespace的域中即可以放数据类型变量还可以放函数,结构体等。
使用namespace需要注意的是:
1.namespace的使用只能放在全局域或着嵌套使用。
2.多个重名的namespace会被系统认为一个namespace,不会冲突。
3.c++命名空间都放在一个std的命名空间。
1.2namespace命名空间的使用
命名空间的使用参照如下代码:
#include<stdio.h>
#include<stdlib.h>
namespace a
{
int rand = 12;
int add(int x, int y)
{
return x + y;
}
struct b
{
int val;
int* next;
};
}
int main()
{
printf("%d", a:: rand);
printf("%d", a::add(1, 1));
a::b c;
c.next = NULL;
c.val = 0;
}
只需要在要调用的元素前面加入命名空间的名字+::就行了,如以上代码命名空间名字为a要调用rand可以"a::rand"进行调用。
1.2.1 using的使用
在调用命名空间时总是要在前面加上一段,这在代码少时还好,当代码一多,这操作无疑太过于麻烦了,在这时我们可以用using将命名空间展开。using的使用如下:
#include<stdio.h>
#include<stdlib.h>
namespace a
{
int rand = 12;
int add(int x, int y)
{
return x + y;
}
struct b
{
int val;
int* next;
};
}
using namespace a;
int main()
{
printf("%d", add(1, 1));
b c;
c.next = NULL;
c.val = 0;
}
using的使用也可以单独展开命名空间一个成员。
#include<stdio.h>
#include<stdlib.h>
namespace a
{
int rand = 12;
int add(int x, int y)
{
return x + y;
}
struct b
{
int val;
int* next;
};
}
using a::add;
int main()
{
printf("%d", add(1, 1));
a::b c;
c.next = NULL;
c.val = 0;
}
using不推荐做项目时展开全部命名空间,这样的风险太大,在刷题的过程中如果命名空间的成员不会冲突可以使用using,一般在做项目当中使用using只展开某一个单独的成员。
2.c++中的输入和输出
2.1 std::count
std::cout 是 ostream 类的对象,它主要⾯向窄字符的标准输出流。
std::out的作用可以于c语言当中的printf进行类比。
#include<iostream>
int main()
{
int a = 1;
double b = 1.1;
std::cout << "a=" << a;
}
运行结果:
2.2 std::endl
std::endl 是⼀个函数,流插⼊输出时,相当于插⼊⼀个换⾏字符加刷新缓冲区。std::end可以类比于c语言中的转义操作符‘\n’。
#include<iostream>
int main()
{
int a = 1;
double b = 1.1;
std::cout << "a=" << a<<std::endl<<"b="<<b;
}
运行结果:
2.3 std::cin
std::cin 是 istream 类的对象,它主要⾯向窄字符(narrow characters (of type char))的标准输⼊流。
std::cin的作用可以类似于c语言当中的scanf。
#include<iostream>
int main()
{
int a = 1;
double b = 1.1;
std::cout << "a=" << a<<std::endl<<"b="<<b<<std::endl;
std::cin >> a;
std::cin >> b;
std::cout << "a=" << a << std::endl << "b=" << b << std::endl;
}
<<是流插⼊运算符,>>是流提取运算符。
使⽤C++输⼊输出更⽅便,不需要像printf/scanf输⼊输出时那样,需要⼿动指定格式,C++的输⼊输出可以⾃动识别变量类型(本质是通过函数重载实现的),其实最重要的是C++的流能更好的⽀持⾃定义类型对象的输⼊输出。
cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以要通过命名空间的使⽤⽅式去⽤他们。
这⾥我们没有包含<stdio.h>,也可以使⽤printf和scanf,在包含<iostream>间接包含了。vs系列编译器是这样的,其他编译器可能会报错。
3.缺省参数
缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实参则采⽤该形参的缺省值,否则使⽤指定的实参,缺省参数分为全缺省和半缺省参数。
#include<iostream>
int add1(int x = 2, int y = 1)//全缺省参数
{
return x + y;
}
int add2(int x, int y=3)//半缺省参数
{
return x + y;
}
int main()
{
std::cout << add1() << std::endl;//全缺省参数可以不传参
std::cout << add1(4, 4) << std::endl;//当传入实参时缺省参数不起作用
std::cout << add2(2) << std::endl;//半缺省参数必须传入参数
}
运行结果:
C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。
那么当函数的定义及声明都出现缺省参数会发生什么呢?观察以下代码:
#include<iostream>
int add1(int x=0, int y=1 )
{
return x + y;
}
int main()
{
int add1(int x = 2, int y = 1);
std::cout << add1() << std::endl;
}
运行结果:
可以看初当函数的声明出现时,即使函数的定义上同样有缺省参数,可还是调用函数声明的缺省参数。函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。
4.函数的重载
C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调⽤就表现出了多态⾏为,使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同名函数的。
#include<iostream>
int add(int x, int y)
{
std::cout << "int add1(int x, int y)" << std::endl;
return 0;
}
//参数类型不同
double add(double x, double y)
{
std::cout << "int add1(double x, double y)" << std::endl;
return 0;
}
//参数个数不同
int add(int x, int y, int z)
{
std::cout << "int add(int x, int y, int z)" << std::endl;
return 0;
}
int main()
{
add(1, 1);
add(1.0, 1.0);
add(1, 1, 1);
}
运行结果:
5.引用
引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间,它和它引⽤的变量共⽤同⼀块内存空间。就比如:土豆也可以叫做马铃薯,马铃薯就是土豆的别名,无论是马铃薯还是土豆都是指向一个物品。
引用的使用:数据类型& 引用别名=引用对象;
#include<iostream>
int main()
{
int a = 1;
int& b = a;
std::cout << a << std::endl;
std::cout << b << std::endl;
b = 5;
std::cout << a << std::endl;
std::cout << b << std::endl;
}
运行结果:
5.1引用在函数中的使用
在学习c语言函数当中,我们知道函数的形参是一份临时拷贝,不会影响实参,想要改变实参可以传入地址,在这里我们又学习了一种可以改变的实参的方法,即在形参前面加&来表示引用,实习代码如下:
#include<iostream>
void swap(int& x, int& y)
{
int a=0;
a = x;
x = y;
y = a;
}
int main()
{
int x = 2, y = 3;
std::cout << "x=" << x << std::endl << "y=" << y << std::endl;
swap(x, y);
std::cout << "x=" << x << std::endl << "y=" << y << std::endl;
}
运行结果:
5.2const引用
#include<iostream>
int main()
{
const int a = 1;
int& b = a;
}
运行如上代码,程序会报错
在这里报错的原因是因为权限被放大了,a因为被const修饰,所以无法改变a的值,但如果用一个没有被const修饰的别名去引用a,会导致b能改变,但a不能改变,但a与b是一个数据。
如果在b的前面上加个const如下:
#include<iostream>
int main()
{
const int a = 1;
const int& b = a;
}
程序就能正常运行了。那么观察如下代码:
#include<iostream>
int main()
{
int a = 1;
const int& b = a;
}
该代码也能正常运行,因此我们可以得出结论:权限可以被缩小,但不能被放大。
需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样⼀些场景下a*3的和结果保存在⼀个临时对象中, int& rd = d 也是类似,在类型转换中会产⽣临时对象存储中间值,也就是时,rb和rd引⽤的都是临时对象,⽽C++规定临时对象具有常性,所以这⾥就触发了权限放⼤,必须要⽤常引⽤才可以。
6.NULLptr
观察如下代码:
#include<iostream>
void f(int x)
{
std::cout << "f(int)" << std::endl;
}
void f(int* x)
{
std::cout << "f(int)" << std::endl;
}
int main()
{
f(NULL);
}
运行结果:
本想通过f(NULL)调用f(int *x),却调用了f(int),这是因为在c++当中NULL可能被定义为字⾯常量0,或者C中被定义为⽆类型指针(void*)的常量。不论采取何种定义,在使⽤空值的指针时,都不可避免的会遇到⼀些⿇烦,本想通过f(NULL)调⽤指针版本的f(int*)函数,但是由于NULL被定义成0,调⽤了f(int x),因此与程序的初衷相悖。
而像f((void*)NULL);调⽤会报错。
因此 C++11中引⼊nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式地转换为指针类型,⽽不能被转换为整数类型。
标签:std,main,int,namespace,缺省,C++,初识,include From: https://blog.csdn.net/ggbongjds/article/details/142908176