C++基础

1.指针和引用

1.1定义与特点

指针本身命名变量,有地址,可变,可以为空值;
引用是变量的别名,必须初始化,从一而终不可变,不存在指向空值的引用。

1.2用途

指针:用于动态内存分配数组操作函数参数传递
引用:用于函数参数传递操作符重载创建别名

2.数据类型

2.1整型

short:至少16位;
int:至少与short一样长;
long:至少32位&&至少与int一样长;
long long:至少64位&&至少与long一样长

2.2无符号类型

不存储负数值的类型,增大变量能够存储的最大值。
注:int一般被设置为自然长度,选择类型时一般选用int类型。

3.关键字

3.1const

const的语义为只读。修饰的值不能改变,必须在定义时就给它赋予初值

3.1.1常量指针

常量的指针,是底层const,即指针指向的是一个只读的对象。const在*左边,靠近数据类型。
示例:

int a = 10;
int b = 20;
const int * pa = &a;	//int const * pa = &b;
pa = &b;	//pa的值可变
cout<<*pa<<endl;    //20 
3.1.2指针常量

指针类型的常量,是顶层const,指针常量只能在定义时初始化,之后不能改变。const在*右边,靠近变量名。

int a = 10;
int * const pa = &a;
*pa = 20;	//pa指向的对象值可变
cout<<*pa<<endl;    //20
3.1.3修饰引用

表示引用的值是常量,不能通过引用修改。

3.2static

static用于控制变量和函数生命周期作用域访问权限

3.2.1修饰变量

静态变量在程序的整个生命周期存在,不会因为离开作用域而被销毁,但修饰的局部变量还是只能在声明它的函数内可见。默认初始化为0(基本数据类型)。
如果修饰的是类的成员变量,所有类的对象共享同一个静态成员变量,且必须在类外部定义,以分配内存

3.2.2修饰函数

一般修饰类的成员函数,静态成员函数可以通过类名调用而不需要创建对象,不能直接访问非静态成员变量或非静态成员函数。

class Example{
    static int val;
public:
    static void anotherStaticMethod(){
        cout<<"I am another static method!"<<endl;
    }
    static void staticMethod(){
        cout<<val<<endl;    
        anotherStaticMethod();
    }
};

int Example::val = 10;

int main(){
    Example::staticMethod();
    //10
    //I am another static method!
    return 0;
}

3.4. define、typedef、inline

define:定义预编译时处理的宏字符串替换,无类型检查,不安全。用来防止头文件重复引用。
typedef:有对应的数据类型,有类型安全检查,在编译运行时起作用。
inline:对编译器的一种要求(编译器可以拒绝),inline会将其修饰的函数编译生成的函数体直接插入到被调用的地方,没有普通函数的压栈,跳转和返回开销。内联函数是一种特殊的函数,会进行类型检查。

注:内联函数中不能有循环语句,过多的条件判断,函数体要小,且必须声明在调用语句之前。

3.5.new/delete和malloc/free

new/delete:C++的运算符,自动计算要分配的内存大小,除了分配和释放内存还会调用构造和析构函数,返回定义时具体类型的指针,失败抛出bad_alloc异常,是类型安全的;
malloc/free:C++/C语言的标准库函数,要手动计算内存大小,只分配和释放内存,返回的是void*类型的指针,需要进行类型转换,不是类型安全的;

3.6.constexpr

表示 ”常量“ 的语义,且只能定义编译期常量,一个constexpr标记的变量或函数是const的,反之则不是。
constexpr修饰的指针是常量。修饰的函数的返回类型和所有形参类型都是字面值类型,函数有且只有一条return语句。

3.7volatile

是类型修饰符,影响编译器的结果,修饰的变量有关的操作,不会编译优化,也就是变量的值每次都只会去内存中取,而不会去寄存器中取。

3.8struct 和class

通常struct用于一组相关的数据(也可以有函数),成员默认public,继承默认public;
class包括数据和操作,成员默认private,继承默认private;

3.9前置++与后置++

class Example{
public:
    int val;
    //前置++
    Example &operator++(){
        val += 1;
        return *this;
    }
    //后置++
   	const Example operator++(int){	//形参只是为了作区分//不能返回引用
        const Example tmp = *this;	//const是为了防止++++出错的情况
        val += 1;
        return tmp;
    }
};

int main(){
    Example t;
    t.val = 0;
    cout<<t.val<<endl;	//0
    ++t;
    cout<<t.val<<endl;	//1
    t++;
    cout<<t.val<<endl;	//2
    return 0;
}

注:推荐使用前置++,不会创建临时对象,也就不会有构造和析构造成的额外开销。

4.函数指针

指向函数指针变量,用于存储函数地址,允许运行时动态选择要调用的函数。

int add(int a, int b){
    return a+b;
}

int main(){
    int (*pExample)(int, int);
    pExample = &add;
    cout<<add(1, 2)<<endl;  //3
    return 0;
}

使用场景:

  • 回调函数:向一个函数传递函数指针,以在合适的时候调用及可插拔的特性;
  • 函数指针数组:根据不同的状态调用不同的函数;
  • 动态加载库:实现动态链接库的调用;
  • 多态实现:虚函数和函数指针结合使用,实现动态多态;
    注:指针函数,返回指针类型的函数,尽量不要这么做。
int * getPtr(){
	int x = 10;
	return &x;
}

5.变量使用场景

(从作用域,生命周期,关键字,初始化等方面考量)
静态局部变量:定义的函数内,static修饰,第一次调用时初始化,与程序的生命周期相同。
全局变量:定义在函数和类外,作用域和生命周期都在程序,通常用于共享数据。

6.强制类型转换

static_cast:用于基本类型之间的转换,及将任何类型的表达式转换成void类型。上行转换安全,下行转换不安全。

class Base {
public:
    virtual void print() {
        cout << "Base class" << endl;
    }
};

class Derived : public Base {
public:
    void print() override {
        cout << "Derived class" << endl;
    }
};

int main(){
    Base* basePtr = new Derived();
    basePtr->print();       //Derived class
    // 使用 static_cast 将基类指针转换为派生类指针
    Derived* derivedPtr = static_cast<Derived*>(basePtr); //下行是不安全的

    // 调用派生类的方法
    derivedPtr->print();    //Derived class

    char c = 'a';
    int i = static_cast<int>(c);    //97
    cout<<i<<endl;
    c = static_cast<char>(i);       //a
    cout<<c<<endl;
    return 0;
}

dynamic_cast:只用于存在虚函数父子关系的强制类型转换。转换后必须是类的指针、引用或void*。对于指针/引用,转换失败返回nullptr/抛出异常。下行转换有类型检查,比static_cast更安全。

class Base {
public:
    virtual void print() { cout << "Base class" << endl; }
};

class Derived : public Base {
public:
    void print() override { cout << "Derived class" << endl; }
};

int main() {
    Base* basePtr = new Derived();

    // 使用 dynamic_cast 将基类指针转换为派生类指针
    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);

    if (derivedPtr) {
        // 如果转换成功,调用派生类的方法
        derivedPtr->print();
    } else {
        // 如果转换失败,则 basePtr 不是派生类的指针
        cout << "Cannot convert to Derived class" << endl;
    }

    return 0;
}

reinterpret_cast:将整型转换为指针,指针转换为数组以及指针和引用的转换。
const_cast:常量指针/引用转换为非常量指针/引用,指向的对象相同。去掉类型的const或volatile属性。

class MyClass {
public:
int value;
    MyClass(int value) : value(value) {}

    int getValue() const { return value; }
};

int main() {
    const MyClass obj(10);

    // 使用 const_cast 将 const 对象转换为非 const 对象
    MyClass& nonConstObj = const_cast<MyClass&>(obj);

    // 修改非 const 对象的值
    nonConstObj.value = 20;

    // 打印修改后的值
    cout << obj.getValue() << endl; // 输出:20

    return 0;
}
  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值