一、历史
C++是在C上继承拓展的!
java是一家公司(甲骨文)借鉴C++生成的!
C#是微软借鉴java生成的!
二、命名空间
当我们定义一个名叫rand的变量,但是由于stdlib头文件里面有个函数跟rand重名!因此会发生命名冲突!
因此为了解决该问题,C++引入了命名空间的定义!
同一个域里面不可以定义同一个变量!
不同的域里面可以定义同一个变量!(局部变量访问优先)
常见的域有:类域、命名空间域、局部域、全局域
#include<stdio.h>
#include<stdlib.h>
int a = 0;
int main()
{
int a = 1;
printf("%d\n", a);
printf("%d\n", ::a);
return 0;
}
对于上面这段代码, 打印的第一个a为局部变量;第二个::a为全局变量。
::被称为域作用限定域!
::的左边为空白!(空格无影响),表示的就是在全局域访问!
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
int a = 0;
namespace bit
{
int a = 1;
}
int main()
{
// int a = 2;
printf("%d\n", a); // 打印结果为0
//printf("%d\n", ::a);
return 0;
}
默认的访问顺序为 局部域->全局域
如果不指定不会访问命名空间域!(默认不会的)
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
//int a = 0;
namespace bit
{
int a = 1;
}
int main()
{
// int a = 2;
printf("%d\n", a);
//printf("%d\n", ::a);
return 0;
}
代码会直接报错!
有两种方法来访问命名空间域:
- 展开了命名空间域!
- 指定访问的的命名空间域!
1、展开命名空间域
namespace bit
{
int a = 1;
}
// 展开命名空间
using namespace bit;
此时相当于将命令空间中的a暴漏在全局域中!
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
int a = 0;
namespace bit
{
int a = 1;
}
// 展开命名空间
using namespace bit;
int main()
{
printf("%d\n", a);
return 0;
}
此时会报错,a变量不明确!因为两个变量都位于全局域当中!
2、指定命名空间
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
int a = 0;
namespace bit
{
int a = 1;
}
// 展开命名空间
using namespace bit;
int main()
{
int a = 2;
printf("%d\n", a);
printf("%d\n", ::a);
printf("%d\n", bit::a);
return 0;
}
通过作用域限定符指定命名空间,从而访问bit命令空间里面的变量!
展开指的是编译时是否会去命名空间中搜索!
最好不要轻易将命名空间暴漏给全局域!
3、命名空间的定义
-
正常的命名空间定义
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}
中即为命名空间的成员。
命名空间中可以定义变量/函数/类型!
namespace bit
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
- 命令空间可以嵌套
namespace N1
{
int a = 0;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N2
{
int a = 2;
int d;
int Sub(int left, int right)
{
return left - right;
}
}
}
此时N1和N2的a为两个不同的变量!
int main()
{
printf("%d\n",N1::a); // 访问N1中的a
printf("%d\n",N1::N2::a); // 访问N2中的a
printf("%d\n",N1::Add(1,2));
return 0;
}
- 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
例如有一个quequ.h的头文件定义了如下:
namespace cc
{
int x = 0;
}
有一个stack.h的头文件定义了如下:
namespace cc
{
int y = 0;
}
此时如果有一个test.c的文件:
#include"stack.h"
#include"queue.h"
int main()
{
printf("%d\n",cc::x);
printf("%d\n",cc::y);
return 0;
}
可以访问x和y!(合并到了一个命名空间!)
如何解决同一个命名空间定义变量名相同的变量?
使用命名空间的嵌套!
std标准库
std也被称作C++标准库,包括STL库和C++库
在C++编程中,using namespace std; 是一条指令,用于告诉编译器在当前作用域中使用标准命名空间(std)。标准命名空间包含了C++标准库中的所有函数、对象和类型,例如cout、cin、vector、string等。
详细解释
- 命名空间(namespace):
命名空间是C++中的一种机制,用于防止命名冲突。标准库中所有的名称都被定义在命名空间std中。例如,标准输出流对象cout的完整名称是std::cout。
- using namespace std;的作用:
当你使用using namespace std;时,你告诉编译器在当前作用域中默认使用std命名空间中的所有名称。这意味着你可以直接使用cout、cin等,而不需要每次都写std::cout、std::cin。
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
在这个例子中,由于使用了using namespace std;,我们可以直接使用cout和endl,而不需要写成std::cout和std::endl。
注意事项
- 命名冲突:
使用using namespace std;可能会导致命名冲突。如果你的代码中包含了与标准库中名称相同的变量或函数名,可能会引发冲突。例如:
#include <iostream>
using namespace std;
void sort() {
// 自己定义的sort函数
}
int main() {
sort(); // 这是调用自己的sort函数还是标准库的sort函数?
return 0;
}
在这种情况下,编译器可能会产生混淆,不知道你是要调用标准库中的sort函数还是你自己定义的sort函数。
推荐做法:
为了避免命名冲突,许多开发者更倾向于在需要使用标准库名称时显式地使用std::前缀,特别是在大型项目或库开发中。
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
这样可以清楚地知道每个名称的来源,减少命名冲突的风险。
总之,using namespace std; 是一个方便的工具,可以简化代码的书写,但在使用时需要小心,特别是在大型项目中,以避免潜在的命名冲突。
<iostream> 是 C++ 的一个头文件,用于包含输入输出流库。这个库提供了处理输入和输出的功能,例如使用 std::cout 输出到控制台,或使用 std::cin 从控制台读取输入。
总结来说:
- #include<iostream> 用于引入输入输出功能。
- using namespace std; 使得可以直接使用 std 命名空间中的标识符,简化代码书写。
将命名空间中某个成员引入
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
可以避免将整个命名空间展开,造成容易出错
总结:命令空间是为了解决C语言的缺陷:即命名冲突!
三、C++输入&输出
std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中!
cout << "hello world";
- 相当于把"hello world"流入到显示器当中!
- cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含<
iostream >头文件中。
cout << "hello world"<<'\n'<<endl;
- 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。
C++的输入输出可以自动识别变量类型。
C++控制输出精度和宽度比较复杂!且不容易记住,建议使用C语言的输出形式控制精度!
printf的输出比C++的cout输出快!
-
缓冲机制:
printf
使用的是C标准库的stdio.h
,其输出是基于缓冲区的。默认情况下,标准输出是行缓冲的,这意味着输出会在遇到换行符时刷新。cout
使用的是C++标准库的iostream
,其输出也是基于缓冲区的,但它还涉及到对象和流操作,这可能会增加一些开销。此外,cout
默认是同步与C的标准输出流(printf
),这也会影响性能。
-
同步机制:
- C++的
iostream
库默认与C标准库的stdio
同步,以确保混合使用printf
和cout
时的输出顺序正确。这种同步机制会带来额外的性能开销。 - 你可以通过调用
std::ios::sync_with_stdio(false);
来禁用这种同步,从而提高cout
的性能: #include <iostream> using namespace std; int main() { ios::sync_with_stdio(false); // 禁用与stdio的同步 cout << "Hello, World!" << endl; return 0; }
- C++的
-
格式化和类型安全:
printf
是一个基于格式字符串的函数,它直接操作C风格的字符串,效率较高,但缺乏类型安全和灵活性。cout
是类型安全的,它使用运算符重载来处理不同类型的数据,这虽然带来了更高的灵活性和安全性,但也增加了运行时的开销。
-
模板和流操作:
cout
使用了模板和流操作,这些都是C++语言特有的高级特性,虽然提供了更强大的功能和更好的类型安全性,但也会引入额外的开销。