0
点赞
收藏
分享

微信扫一扫

【深蓝C++】【第2章】【知识点汇总】

书写经典 2022-05-04 阅读 46
c++clion

【深蓝C++】【第2章】【知识点汇总】

0 前言

  • 环境是ubuntu18.06
  • IDE是clion

1 知识点汇总

1.1查看main函数返回的值

终端执行:

echo $?

如下:

  • 操作系统会掉哟main,那么main的返回值就给操作系统
bupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ ./helloworld 
Hello, World!

bupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ echo $?
0
  • 返回 0 代表程序运行成功
  • main函数返回值即使不是void类型。如果没有写返回语句,那么默认返回一个 0
  • main函数的返回类型一定是int

1.2 头文件<>和“”区别

  • 使用“”,系统会从当前的目录开始来寻找头文件
  • 使用<>,系统从环境变量开始寻找
  • 通常来讲,头文件属于自己编写的,属于当前工程的,会用””
  • 使用C++标准库的头文件,使用<>,且其头文件没有.h/.hpp等类型的后缀

1.3 输入cin和输出cout、cerr、clog的使用

  • isotream:标准库提供的IO接口,用于与用户交互
  • 输入流:cin;输出流:cout/cerr/clog
  • 输出流的区别:1、输出目标;2、是否立即刷新缓冲区
  • 缓冲区与缓冲区刷新:std:flush;std:endl;

1.3.1 cout、cerr、clog

  • 将cout和cerr的信息存储起来
    代码如下:
#include <iostream>

int main() {
    std::cout << "out from cout";
    std::cerr << "out from cerr";
}

编译并运行该代码输出:

out from coutout from cerr

则下面可以将其结果分别重定向到不同的文件中:

bupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ ./helloworld >txt1 2>txt2
bupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ cat ./txt1 
out from coutbupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ cat ./txt2 
out from cerrbupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ 
  • cout是程序系统的输出
  • cerr是一些错误的信息
  • clog和cerr基本上相似,下面看一个程序:
#include <iostream>

int main() {
    std::cout << "out from cout";
    std::cerr << "out from cerr";
    std::clog << "out from clog";
}

输出为:

out from coutout from cerrout from clog

然后同样重定位到不同的文件:

bupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ ./helloworld >txt1 2>txt2
bupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ cat ./txt1 
out from coutbupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug$ cat ./txt2 
out from cerrout from clog
  • cerr和clog的区别在于是否立即刷新缓冲区,cerr立即刷新,clog日志信息不是立即刷新,缓冲区满了才会自动输出

1.3.2 刷新缓冲区 std::flush、std::endl

  • flush是刷新缓冲区,将缓冲区中的信息显示
  • endl是刷新缓冲区并且换行
  • 刷新缓冲区会影响程序的执行速度,大量的使用刷新缓冲区不是一个很好的行为

1.4 名词空间namespace

1.4.1 自定义名字空间基本使用方式

  • 名字空间:用于防止名称冲突
  • 访问名字空间中元素的3种方式:域解析符::;using语句;名字空间别名
#include <iostream>

namespace Namespace1
{
    void fun()
    { }
}

namespace Namespace2
{
    void fun()
    { }
}

int main() {
    //way 1
    Namespace1::fun();

    //way 2
    //可以写在函数体外,但是不推荐
    //因为本身使用命名空间就是为了防止冲突
    using namespace Namespace2;
    fun();
    
    //way 3
    namespace ns1 = Namespace1;
    ns1::fun();

}

  • 使用方式2的时候应该注意:命名空间声明可以写在函数体外,但是不推荐,因为本身使用命名空间就是为了防止名词冲突;
  • 在cpp文件这样还好,如果在头文件这样写非常危险,因为如果引入这样写的一个头文件的源文件,都会有名词冲突的危险
  • 最安全的写法就是使用方式1或者方式3

1.4.2 std名字空间

  • C++标准库所定义的名字空间

1.5 查看C++文件生成的.o文件所有的外部链接及反向操作

  • 名字空间和名称改编(name mangling)

1.5.1 name mangling

linux下的命令:

nm ./main.cpp.o

如下展示了main.cpp包含的所有外部链接:

bupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug/CMakeFiles/helloworld.dir$ nm ./main.cpp.o 
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
000000000000009b t _GLOBAL__sub_I__ZN10Namespace13funEv
000000000000000e T main
0000000000000052 t _Z41__static_initialization_and_destruction_0ii
0000000000000000 T _ZN10Namespace13funEv
0000000000000007 T _ZN10Namespace23funEv
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cerr
                 U _ZSt4clog
                 U _ZSt4cout
0000000000000000 r _ZStL19piecewise_construct
0000000000000000 b _ZStL8__ioinit
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc

其中

0000000000000000 T _ZN10Namespace13funEv
0000000000000007 T _ZN10Namespace23funEv

就是链接的自己所写的名字空间的fun文件

1.5.1 de name mangling

  • linux下命令
nm ./main.cpp.o | c++filt -t

如下:

bupo@bupo-vpc:~/shenlan/C++/cap2/cmake-build-debug/CMakeFiles/helloworld.dir$ nm ./main.cpp.o | c++filt -t
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
000000000000009b unsigned short _GLOBAL__sub_I__ZN10Namespace13funEv
000000000000000e T main
0000000000000052 unsigned short __static_initialization_and_destruction_0(int, int)
0000000000000000 T Namespace1::fun()
0000000000000007 T Namespace2::fun()
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::cerr
                 U std::clog
                 U std::cout
0000000000000000 r std::piecewise_construct
0000000000000000 bool std::__ioinit
                 U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)

  • 两者不会改变main,之所以改编是因为名称可能会和程序当中其他的名称相冲突(函数重载),main是唯一的,不可能同名,所以不会对其进行改变

1.6 系统I/O

  • C/C++系统I/O比较
#include <iostream>
#include <cstdio>
int main()
{
    std::cout << "Hello World" << std::endl;
    printf("Hello World\n");
}

  1. printf:使用直观,但容易出错
  2. cout:不容易出错,但书写冗长
  3. C++20格式化库:新的解决方案
#include <iostream>
#include <cstdio>
int main()
{
    int x = 10;
    std::cout << "I have " << x << " pens\n";
    printf("I have %d pens\n", x);
}

1.7 ==使用的技巧,if和while循环

  • 可以将常量放在==左边以防止误用 ,可以在常量再加上一个const
    如下:
#include <iostream>

int main()
{
    const int x = 42;
    std::cout << "Please input a number: \n";

    int y = 0;
    std::cin >> y;

    if(x == y)
    {
        std::cout << "You are right!\n";
    }
    else
    {
        std::cout << "You are wrong!\n";
    }
}

  • 使用while循环,用于循环执行
#include <iostream>

int main()
{
    const int x = 42;
    int y = 0;

    while(x != y)
    {
        std::cout << "Please input a number: \n";
        std::cin >> y;
    }
        std::cout << "You are right!\n";
}

1.8 结构体与自定义数据类型

  • 结构体:将相关的数据放置在一起
  1. 可以通过点操作符(.)访问内部元素
  2. 可以作为函数的输入参数或返回类型
  3. 可以引入成员函数,更好地表示函数与数据的相关性
#include <iostream>

struct Point
{
    int x;
    int y;
    void IncX()
    {
        x = x + 1;
    }
};

Point& fun(Point &p)
{
    p.x = p.x +1;
    return p;
}
int main()
{
    Point p;
    p.x = 3;
    p.y = 4;
    fun(p);
    std::cout << p.x << " " << p.y << '\n';
    p.IncX();
    std::cout << p.x << " " << p.y << '\n';
}

举报

相关推荐

0 条评论