c++(一) :从c到c++

以下内容是c++中,大多是c没有的或与c不同的语言特性。

bool类型

值取true和false.

const 常量标识符

//const int a;  // error,常量必须初始化
const int a = 100;
// a = 200;    // error,不能对常量赋值

const int * p // 定义了一个指向常量的指针变量(*p是常量)
int * const p2 = &a; // p2是常量,需初始化

/* const常量与#define定义的符号常量的区别
* 1.const定义的常量有类型,而#define定义的没有类型,编译可以对前者进行安全检查,对后者只是 * 做简单替换
* 2.const常量在编译时分配内存,#define定义的在预编译进行替换,不分配内存
* 3.作用范围不同,前者作用域为变量的作用域,后者从定义点到程序结束(也可用#undef取消)
*/

// 尽量用const、enum代替#define

内存对齐

  • 是什么:1.编译器为每个“数据单元”安排在某个合适的位置上. 2.c,c++允许干涉内存对齐
  • 为什么:在对齐的内存空间上能更快的访问数据
  • 怎么用:

域运算符::

// 用法1:对与局部变量同名的全局变量进行访问
#include <iostream>
using namespace std;

int var = 100;
int main()
{
    int var = 50;
    cout << var <<endl;   // 50
    cout << ::var << endl; // 100
}

 new与delete

  • 是操作符,不是函数
  • new用于创建堆空间,成功返回首地址, 用法:
  • delete 释放堆空间
    // new:分配内存,调用构造函数
    int *p;
    p = new int;
    char *p_str = new char[50];
    
    // delete:调用析构函数,释放内存
    delete [] p_str;
    delete p;

重载

函数名相同,参数不同(数量,类型,顺序)

引用

  • 就是给一个变量起别名(引用不是变量,只是变量的别名)
    int a = 100;
    int &b = a; // b是a的别名
    b = 200;
    cout << b <<" " << a << endl; // 200 200
  • 引用没有自己的空间
  • 对引用的改变相当于对原变量的改变
  • 用法:
    // 1.作为函数参数
    void swap(int &a, int &b)
    {
        int tmp = a;
        a = b;
        b = tmp;
    }

    // 2.引用作为返回值,主要目的是可以将函数放在赋值运算符的左边(不能返回对局部变量的引用)
    #include <iosteam>
    using namespace std;

    int a[] = {0, 1, 2, 3, 4};
    int& index(int i)
    {
    return a[i];
    }
    int main()
    {
    index(3) = 100;   // 引用作为函数返回值,使得函数可以放在赋值运算符左边
    // 函数返回引用,引用在函数返回的时候初始化
    cout << a[3] << endl; // 100
       return 0;
    }

 引用与指针的区别

  1. 引用访问变量是直接访问,指针是间接访问
  2. 引用没有自己的内存空间,指针有
  3. 引用初始化后不能再引用其他变量,指针可以

(c++中尽可能使用引用)

 内联函数

1.背景

首先来看函数调用的过程:

  建立占空间->保护现场->传递参数->控制程序执行的转移->...

对于一些本身功能简单,代码简短,使用频率很高的函数,频繁调用会严重影响程序效率,可以通过将代码嵌入程序中,但这样又会产生大量重,为了解决效率与重复的矛盾,c++提供了一种方法——内联函数(定义函数时使用 inline 修饰).

内联函数是在编译的时候展开的(相当于嵌入到代码中,不存在函数调用).

2.内联函数与带参数宏的区别

  • 内联函数要求实参形参类型一致,先对实参表达式求值,然后传递给形参;而宏调用时只用形参进行简单的替换.
  • 内联函数在编译时使用、在调用的地方将代码展开;宏调用在预编译时进行替换

新的类型转换

旧式:

  (T)expr

新式:

  1. const_cast<T>(expr)
    // 移除对象的常量性
    // 一般用于指针或者引用
    // 去除const限定不是为了修改它的内容
    // 通常是为了函数能接受这个参数
    #include <iostream>

    void fun(int &val)
    {
      cout << "test" << endl;  
    }
    using namespace std; int main() { const int val = 100; // int n = const_cast<int> (val); // error,不能用于对象 int n = val; // int *p = &val; error,无法从const int * 转换为int * int *p = const_cast<int*>(&val); *p = 200; cout << val << endl; // 100,并未改变,产生临时对象



    const int val2 = 200;
    // int& ref2 = val2; 非const引用不能指向const对象
    int& ref2 = const_cast<int&>(val2);
    ref2 = 300;
    cout << val2 << " " << ref2 << endl; // 200 300

      // func 函数要求传入非const引用,这时可以用const_cast对val2进行转换
    fun(const_cast<int&>(val2)) return 0; }
  2. static_cast<T>(expr)
    1. 编译器的隐式转换:编译器自动转换,一般来说是安全的,比如说int a; short b; a = b; 编译器隐式执行的任何类型转换都可以有static_cast完成;
    2. 当一个较大的算术类型赋值给较小的类型时,可以使用static_cast进行强制转换,例:
      // double -> int
      #include <iostream> using namespace std; int main() { int n = static_cast<int>(3.14); cout << n << endl; // 3 return 0; }

       

    3. 可以将void*指针转换为某一类型的指针;

    4. 可以将基类指针转成派生类指针
    5. 无法将const转换为nonconst
  3. reinterpret_cast<T>(expr)
    /*
     * reinterpret_cast:将数据以二进制存在形式的重新解释
     */
    int i;
    char *p = "This is a example.";
    i = reinterpret_cast<int>(p);
    // 此时结果,i与p完全相同
    
    
    int *ip;
    char *pc = reinterpret_cast<char *>(ip);
    // 需要记得pc所指向的真实对象是int型,并非字符串。
    // 如果将pc当作字符指针进行操作,可能会造成运行时错误
    // 如int len = strlen(pc);
  4. dynamic_cast<T>(expr): 只接受基于类对象的指针或引用的类转换

 

尽可能避免转换,若无法避免使用新式类型转换

 

转载于:https://www.cnblogs.com/ezhengnan/p/3661944.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值