第三章---深度分析注释、预处理指令、万能头文件、using namespace std;、main 函数、关闭同步流、cin、cout、endl、return 0

C++ 是一种广泛使用的面向对象编程语言。“Hello World”程序是学习任何编程语言的第一步,也是您将学习的最直接的程序之一。下面我将以这样一个简单的代码对其详细分析。

要编写和运行 C++ 程序,您需要在计算机上设置本地环境。如果没有设置本地环境,请参阅这篇文章设置 C++ 开发环境。

《C++学习教程》–40篇文章学懂C++ --第二篇—设置C++开发环境》

下面是打印 Hello World 的 C++ 程序。
// C++ program to display "Hello World"

#include <iostream>
//#include <bits/stdc++.h>   万能头文件
using namespace std;
// Main() function: where the execution of
// program begins
int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    // Prints hello world
    cout << "Hello World" << endl;
    cout << "Hello World" << "\n" ;
    return 0;
}
输出
Hello World
Hello World

现在让我们了解上述程序的每一行和术语。

1.注释 : ///* */

// C++ program to display "Hello World" 在 C++ 中,任何以 // 开头而不带引号或/* */ 之间的都是注释。注释是一种非执行的说明性文本,用于解释代码的功能或描述代码的某个部分。

2.预处理指令

C++在编译源代码之前会进行预处理。预处理指令是以 # 开头的行,它们指示预处理器执行特定的操作。#include 指令告诉预处理器在编译之前将指定的文件内容插入到当前源文件中。

标准输入输出流库(iostream)

iostream 是C++标准库中的一个头文件,它定义了处理输入输出流的类。这些类支持从标准输入设备(通常是键盘)读取数据,以及向标准输出设备(通常是屏幕)写入数据。
以下是 iostream 中定义的一些主要对象和操作:

  • std::istream:输入流类,用于从数据源读取数据。std::cinstd::istream 的一个实例,它关联到标准输入。
  • std::ostream:输出流类,用于向数据目标写入数据。std::coutstd::ostream 的一个实例,它关联到标准输出。
  • std::iostream:输入输出流类,继承了 std::istreamstd::ostream 的功能,允许同时进行读写操作。
  • std::endl:操纵符,用于输出一个换行符并刷新输出缓冲区。
  • std::flush:操纵符,用于刷新输出缓冲区。

使用#include< iostream>

当你在C++程序中使用 #include <iostream> 时,可以执行以下操作:

1.声明命名空间:使用 using namespace std; 声明命名空间,这样就不需要在标准库对象前加上 std:: 前缀。
#include <iostream>
using namespace std;
int main() {
    cout << "Hello, World!" << endl;
    return 0;
}
2. 使用标准输入输出:直接使用 cincout 进行输入输出操作。
#include <iostream>
int main() {
    int number;
    std::cout << "Enter a number: ";
    std::cin >> number;
    std::cout << "You entered: " << number << std::endl;
    return 0;
}

注意事项

  • #include <iostream> 使用的是尖括号 <>,这表示预处理器首先在标准库路径中查找头文件。如果你想包含本地项目中的文件,通常使用双引号 ""
  • 在包含标准库头文件时,推荐使用 #include <iostream> 而不是 #include "iostream"
  • 为了避免命名空间冲突,一些程序员选择不使用 using namespace std;,而是直接使用 std:: 前缀。
    通过使用 #include <iostream>,你可以轻松地在C++程序中处理标准输入输出,这是C++程序设计中非常基础且常用的功能。

万能头文件 #include <bits/stdc++.h>

#include <bits/stdc++.h> 是一个在许多在线编程竞赛平台和某些编译环境中广泛使用的头文件,尤其是在Codeforces、TopCoder和HackerRank等网站上。

使用万能头文件有很多好处:

  1. 方便快捷、节省时间:只需一个包含指令,就可以使用几乎所有的标准库功能,这大大简化了代码的编写过程。
  2. 减少错误由于不需要记住每个功能对应的头文件,因此减少了因忘记包含头文件而导致的编译错误。
  3. 代码简洁:使用万能头文件可以使代码顶部看起来更加简洁,因为不需要包含一大堆头文件。
  4. 通用性:在不知道具体需要哪些标准库功能的情况下,万能头文件可以作为一个保险的选择,确保所有可能需要的功能都可用。

但是缺点则包括以下几点:

  1. 非标准<bits/stdc++.h>不是C++标准库的一部分,因此可能在某些编译器或环境中不可用。
  2. 性能问题:由于它包含了几乎所有的标准库,因此编译时间可能会更长,生成的可执行文件也会更大。
  3. 代码可读性:使用万能头文件会使得代码的可读性变差,因为不清楚程序实际使用了哪些库。

在正式的编程实践中,推荐根据需要包含相应的标准头文件,这样可以提高代码的清晰度和编译效率。如果你正在准备编程竞赛,那么使用这个头文件是可以接受的,但应该意识到它并不是一个好的编程习惯。

3. using namespace std;

在C++中,using namespace std; 是一个声明,它告诉编译器在当前作用域内使用标准命名空间 std。下面详细讲解这个声明及其相关概念。

命名空间(namespace)

C++中的命名空间是一种组织代码的方式,它可以将全局作用域中的标识符(如变量、函数、类等)分组,以避免命名冲突。例如,两个不同的库可能都有名为 vector 的类,如果直接使用这些类,就会产生命名冲突。通过将它们放在不同的命名空间中,可以避免这种冲突。
标准命名空间 std 包含了C++标准库中的所有标准类型、对象和函数。例如:

  • std::vector 是一个模板类,用于表示可变大小的数组。
  • std::cout 是一个用于输出的输出流对象。
  • std::string 是一个表示字符串的类。

using 声明

using 声明可以让你在不需要完全限定名的情况下访问命名空间中的成员。具体来说,using namespace std; 声明告诉编译器,在当前作用域中,任何未明确指定命名空间的标识符都可以在 std 命名空间中查找。

使用 using namespace std;

当你写下 using namespace std; 时,以下事情会发生:

  1. 简化代码:你可以在代码中直接使用 std 命名空间中的任何标识符,而不需要在它们前面加上 std:: 前缀。
  2. 潜在命名冲突:由于现在所有 std 命名空间中的标识符都可以直接使用,如果你的程序或你使用的库中定义了与 std 命名空间中相同的标识符,就会产生命名冲突。

注意事项

  • 避免全局使用:在全局作用域中使用 using namespace std; 是一种不好的实践,因为它会增加命名冲突的风险,特别是在大型项目中。
  • 局部使用:更好的做法是在函数或局部作用域中使用 using 声明,这样可以限制其影响范围。
#include <iostream>
void printMessage() {
    using namespace std;
    cout << "Hello, World!" << endl;
}
int main() {
    printMessage(); // 在函数内部使用 using 声明
    return 0;
}
  • 使用特定的 using 声明:如果你只需要使用 std 命名空间中的几个标识符,可以单独声明它们,而不是整个命名空间。
#include <iostream>
using std::cout;
using std::endl;
int main() {
    cout << "Hello, World!" << endl; // 只使用了 cout 和 endl
    return 0;
}

总之,using namespace std; 是一个便捷的声明,它可以让代码更简洁,但同时也带来了命名冲突的风险。因此,在使用时应该谨慎,并尽可能限制其作用域。

4. ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

ios::sync_with_stdio(0);

这条语句的目的是告诉C++的IO库,不要将C++的iostream对象(如cin, cout, cerr等)与C的stdio库(如stdin, stdout, stderr等)同步。这通常用于提高输入输出的效率,特别是在需要大量IO操作时。

  • ios::sync_with_stdiostd::ios_base 类的一个枚举值成员,用于控制iostream库是否与C的stdio库同步。
  • 参数 0 表示不进行同步(即禁用同步),而 1 表示启用同步(这是默认行为)。
    禁用同步可以减少iostream操作时的开销,因为iostream不再需要等待stdio操作完成。

cin.tie(0);

这条语句用于解除cin与cout之间的绑定。默认情况下,cin和cout是绑定的,这意味着每次进行cin操作后,都会自动刷新cout缓冲区。

  • cin.tie() 是一个成员函数,返回当前与cin绑定的ostream对象,默认是cout。
  • 参数 0 表示解除绑定,因此cin操作后不会自动刷新cout缓冲区。
    解除绑定可以减少不必要的缓冲区刷新,从而提高性能。

cout.tie(0);

这条语句与 cin.tie(0); 类似,但它是用于解除cout与其他iostream对象的绑定。

  • cout.tie() 是一个成员函数,返回当前与cout绑定的istream对象,默认是cin。
  • 参数 0 表示解除绑定。
    虽然通常情况下,我们主要关注的是解除cin和cout之间的绑定,但在某些情况下,也可能需要解除cout与其他iostream对象的绑定。

ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);

现在我们来看这一组函数:

ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
  • ios::sync_with_stdio(false); 关闭了C++ IO流与C的stdio库的同步,提高了性能。
  • cin.tie(NULL); 解除了cin和cout之间的绑定,这样cin的操作不会导致cout自动flush。
  • cout.tie(NULL); 通常这一行是不必要的,因为前面已经通过 cin.tie(NULL) 解除了绑定,但是它显式地指出了cout不再与任何流绑定。

区别

首先这两种关闭同步流的代码在功能上并没有区别但是,ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); 中的 cin.tie(0)cout.tie(0) 是不正确的用法,应该使用 cin.tie(NULL)cout.tie(NULL) 来解除流之间的绑定。
正确的代码:

ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);

ios::sync_with_stdio(0)ios::sync_with_stdio(false) 实际上是相同的,0 在这里只是表示逻辑上的假值,关闭同步。使用 false 可能更具可读性,但它们的效果是一样的。

总结

使用这条语句的目的是为了优化C++程序的输入输出性能,特别是在算法竞赛或性能敏感的应用中。这些语句通过减少iostream与stdio的同步以及解除cin和cout之间的绑定,来减少不必要的缓冲区刷新,从而提高程序的运行效率。

5. int main() { }

在C++编程语言中,int main() 是程序执行的入口点。每一个C++程序都必须定义一个名为 main 的函数,这样编译器才知道从哪里开始执行程序。以下是关于 int main() 的详细解释:

1. int 关键字

  • int 是一种数据类型,表示 main 函数返回一个整数。
  • 在C++中,main 函数可以返回整数值,这个返回值通常用来表示程序的退出状态。

2. main 函数名

  • main 是函数名,它是预定义的函数名,C++运行时环境会寻找这个函数来启动程序。
  • 函数名是区分大小写的,所以 MainMAIN 不会被识别为程序入口。

3. 括号 ( )

  • 括号用于定义函数的形式参数。空的括号表示 main 函数不接受任何参数,即它是无参函数。
  • 如果 main 函数需要接收命令行参数,可以在括号内添加两个参数:
    int argcchar *argv[]

4. 花括号 { }

  • 花括号定义了函数体的开始和结束。
  • 在花括号内部,可以编写执行具体操作的代码。

5. 函数体

  • { } 之间的代码是 main 函数的函数体,这里编写了程序的主要逻辑。
  • 函数体可以为空,但这意味着程序什么也不做。

总结

int main() 是C++程序的核心,每个程序都必须有且只有一个 main 函数。该函数的原型可以略有不同,比如接受参数的 int main(int argc, char *argv[]),但最基本的形式就是 int main()。当程序运行时,操作系统会调用 main 函数,执行其中的代码,并在 main 函数执行完毕后结束程序的运行。

5. cout<<“Hello World”<<endl ;

在C++中,cout << "Hello World" << endl; 是一个非常基础的语句,用于在控制台输出文本信息。下面详细解释这个语句的各个部分:

cout :

  • cout 是 C++ 中的一个输出流对象,属于 iostream 库的一部分。它是 “character output” 的缩写。
  • cout 用于将数据输出到标准输出设备,通常是计算机的屏幕。

而与输出对应的是输入—cin

cin:

  • cin 是 C++ 中的一个输入流对象,同样属于 iostream 库的一部分。它是 “character input” 的缩写。
  • cin 用于从标准输入设备接收数据,使用 cin 可以方便地从用户那里获取各种类型的数据,如整数、浮点数、字符以及字符串等,并将这些数据存储到相应的变量中。
  • cin 通常与提取运算符 >> 结合使用,通过该运算符可以将输入的数据序列依次赋值给变量。

<< :

  • 这是流插入运算符,用于将右侧的数据插入到左侧的流中。
  • 在这个例子中,<< 运算符被连续使用,表示将多个数据项依次插入到输出流中。

“Hello World” :

  • 这是一个字符串字面量,由双引号包围的字符序列。
  • 在这里,它是要被插入到输出流中的文本信息。

endl :

  • endl 是一个操纵符,它在输出流中使用时具有两个作用:
    1. 输出一个换行符(‘\n’),用于将光标移动到下一行的开头。
    2. 刷新输出缓冲区,确保所有插入到输出流中的内容立即被显示在屏幕上。
      现在,让我们一步步拆解这个语句:
  • cout << "Hello World":这部分将字符串 “Hello World” 插入到输出流 cout 中,这意味着文本 “Hello World” 将被发送到标准输出设备。
  • << endl:这部分将 endl 插入到输出流中。结果是,输出流被刷新,并且屏幕上的光标移动到下一行的开始。
    将这两部分结合起来,cout << "Hello World" << endl; 的作用就是将文本 “Hello World” 打印在屏幕上,并在文本后添加一个新行。

注意!!!!

关闭同步流后最好把 endl 换为 \n

1. 性能:

由于endl会冲洗缓冲区,这可能会导致性能问题,特别是当你频繁地进行输出操作时。关闭同步流后,如果你仍然使用endl,每次输出都会触发缓冲区冲洗,这会是不必要的性能开销,会导致运行时间变长,而使用\n可以避免这种开销。

2. 控制:

使用\n可以让你更精确地控制何时进行缓冲区冲洗。例如,你可以在输出大量数据后,只在必要时调用std::flushstd::endl来冲洗缓冲区。

3. 缓冲策略:

关闭同步流后,操作系统可以更有效地管理缓冲区,因为它可以根据当前系统的状态和输出设备的特性来优化数据的写入。

6. return 0 ;

在C++编程语言中,return 0; 语句是一个基础且重要的概念,它在程序中扮演着特定的角色。以下是对 return 0; 的详细解释:

含义

在C++中,return 0; 通常用于主函数(main 函数)的末尾,它表示程序已经成功执行完毕,并且没有任何错误发生。这里的 0 是一个整型值,它被返回给操作系统,作为程序执行状态的指示。

作用

  • 程序状态指示:在操作系统层面,返回值 0 通常表示程序成功执行,而非零值则表示程序执行过程中出现了错误或异常情况。
  • 函数返回值:在C++中,任何函数都可以通过 return 语句返回一个值。对于 main 函数来说,返回 0 是一种约定俗成的做法。

在例子中,return 0; 语句位于 main 函数的末尾,它告诉操作系统程序已经按照预期成功执行。

好的,这篇文章就分享到这里。如有任何遗漏或错误之处,欢迎指正,感谢您的阅读!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值