C++入门小基础

    众所周知,c++是一门面向对象的语言,不同于c的面向过程。在学习时,首先我们要懂得一些基础入门知识。
目录
        命名空间
        缺省函数
        函数重载
        extern “C”
        引用&
        内联函数inline
        auto关键字(c++11)
        范围for循环(c++11)
        nullptr关键字(c++11)

命名空间

  • 在c/c++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称都将存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是解决这种问题的。
  • c++有一套自己的命名空间std,很多东西的使用都离不开它。

在编写c++代码时,常见的写法如下:

#include<iostream>
using namespace std;

但是有时候我们不想将std全部展开,只想使用其中一部分的时候有两种方法:

#include <iostream>
using std::cout;
using std::endl;
int main()
{
    cout << "Hello World" << endl;
    return 0;
}
#include <iostream>
int main()
{
    std::cout << "Hello World" << std::endl;
    return 0;
}

缺省函数

    缺省函数是声明或定义函数时给函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。在调用缺省函数时,必须从左往右连续的传参,不能空缺。
    全缺省函数:缺省所有参数
    半缺省函数:缺省部分参数,但是必须从右向左连续缺省

#include <iostream>
using std::cout;
using std::endl;
void Func(int a, int b = 1, int c = 2)
{
    cout << a << b << c << endl;
}
int main()
{
    Func(0);
    return 0;
}

函数重载

    函数重载可以理解为一词多义,它允许定义多个功能相似的同名函数,但是参数(个数、顺序、类型)必须不同。
    只是函数的返回值不同,不能构成重载。

#include <iostream>
int Add(int x, int y)
{
    return x + y;
}

double Add(double x, double y)
{
    return x + y;
}

void Func(int a, char b)
{}

void Func(char b, int a)
{}

int main()
{
    Add(1, 2);
    Add(1.0, 2.0);
    return 0;
}

小问题:为什么C++支持函数重载?C为什么不支持?

  1. c++对函数名字进行了修饰,在g++编译器中,函数名被修饰后为(_Z+函数长度+函数名字+类型首字母)。
  2. 在Linux中,采用gcc编译完成后,函数名字的修饰没有发生改变;但是在采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。

extern "C"

    要将某些函数按照C的风格来编译,在函数前加extern “C”,意思是告诉编译器,将该函数按照C语言规则来编译.

引用&

    相当于对已知变量起了一个别名,共用同一块地址空间。
    在定义的时候必须初始化,并且需要考虑权限的放大缩小问题。
    在定义函数时也可以使用引用,函数返回时出了作用域,如果对象还在,可以使用引用;如果不在必须使用传值返回。

#include <iostream>
int main()
{
    int a = 1;
    double b = a; //隐士类型转换
    double& ra = a; //错误
    //a在赋值给ra时,会创建一个临时常量tmp
    //tmp = a; ra = tmp;
    //ra是a的别名可读可写,而tmp是只读的,ra = tmp 会放大权限
    const double& ra = a; //正确
    return 0;
}

小问题:引用和指针的区别?

  1. 引用在定义时必须初始化,指针没有要求
  2. 引用在初始化时引用一个实体后,就不能在引用其它实体,而指针可以在任何时候指向任何一个同类型的实体
  3. 没有NULL引用,但是有NULL指针
  4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  6. 有多级指针,但是没有多级引用
  7. 访问实体方式不同,指针需要显示解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全

内联函数inline

  • 以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。
  • inline是一种以空间换时间的做法,省去调用函数额外开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数。
  • inline对于编译器只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等,编译器优化时会忽略掉内联

小问题:宏的优缺点?

  1. 优点:增强代码的复用性;提高性能
  2. 缺点:不方便调试宏(因为预编译阶段进行了替换);导致代码可读性差,可维护性差,容易误用;没有类型安全的检查

小问题:C++有哪些技术替代宏?

  1. 常量定义:换用const
  2. 函数定义:换用内联函数

auto关键字(c++11)

  • 用auto声明指针类型时,用 auto 和 auto* 没有任何区别,但用auto声明引用类型时则必须加&
  • auto不能作为函数的参数,也不能直接用来声明数组
#include <iostream>
using std::cout;
using std::endl;
int main()
{
    int a = 1;
    auto b = a; //b的类型是根据a的类型推导出来的
    cout << typeid(a).name() << endl; //int
    cout << typeid(b).name() << endl; //int
    auto x = &a;
    auto* y = &a;
    auto& z = a; //引用
    cout << typeid(x).name() << endl; //int*
    cout << typeid(y).name() << endl; //int*
    cout << typeid(z).name() << endl; //int
    return 0;
}

范围for循环(c++11)

    范围for循环本质上是通过迭代器实现的
使用条件:

  1. for循环迭代的范围必须是确定的:对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围
  2. 迭代的对象要实现++和==的操作
  3. 遍历时如果想要更改元素的值,则必须在auto后面加上引用
#include <iostream>
using std::cout;
using std::endl;

void Func(int arr[])
{
    for (auto e : arr) //错误,数组传参时会退化成指针
    {
        cout << e << " ";
    }
    cout << endl;
}

int main()
{
    int arr[] = { 9, 5, 2, 7 };
    //Func(arr);
    for (auto& e : arr)
    {
        e *= 2;
    }
    for (auto e : arr)
    {
        cout << e << " ";
    }
    cout << endl;
    return 0;
}

nullptr关键字(c++11)

在c中:

  1. NULL实际是一个宏,在传统的C头文件(stddef.h)中
  2. NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量

如下程序本意是想通过 Func(NULL) 调用指针版本的 Func(int*) 函数,但是由于NULL被定义成0,因此与程序的初衷相悖

#include <iostream>
using std::cout;
using std::endl;

void Func(int n)
{
    cout << "int" << endl;
}

void Func(int* p)
{
    cout << "int*" << endl;
}

int main()
{
    Func(0); //int
    Func(NULL); //int
    Func(nullptr); //int*
    return 0;
}

在C++11中:

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0) 所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

返回顶部

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值