C++学习笔记1

1. C语言 和 C++的关系

  • C++ 包含了C语言大部分语法,这样c++能轻而易举的使用业界多年积累的C语言优秀的库
  • C++增加了面向对象编程的语法,让C++能更轻松表达面向对象思想编程,面向对象编程思想跟语言无关,用C语言也能实现面向对象思想编程,只是表达起来比较费劲,

2. 指针变量和普通变量

2.1 指针的特点

在C++中,指针变量有以下特点:

  1. 指针变量存储的是内存地址,而不是数据本身。
  2. 指针变量可以指向任何数据类型,包括整数、浮点数、字符、数组、结构体、类等。
  3. 指针变量可以通过解引用运算符*来访问其指向的数据
  4. 指针变量可以通过指针运算符++--来移动指针的位置。
  5. 指针变量可以被用于动态分配内存,例如使用new运算符创建对象。
  6. 指针变量可以被用于传递参数,例如使用指针变量作为函数参数来修改函数外部的变量。
  7. 如果使用new运算符动态分配内存来创建指针变量,则必须使用delete运算符手动释放内存

以下是使用指针变量的示例:

#include <iostream>
int main() {
    int x = 10;
    int* ptr = &x;

    std::cout << "Value of x: " << x << std::endl;
    std::cout << "Address of x: " << &x << std::endl;
    std::cout << "Value of ptr: " << ptr << std::endl;
    std::cout << "Address of ptr: " << &ptr << std::endl;
    std::cout << "Value of *ptr: " << *ptr << std::endl;
    return 0;
}

在上面的示例中,我们定义了一个名为x的整数变量,并使用取地址运算符&将其地址存储在指针变量ptr中。然后,我们使用std::cout语句输出x的值、x的地址、ptr的值、ptr的地址和*ptr的值,分别表示整数变量的值、整数变量的地址、指针变量的值、指针变量的地址和指针变量所指向的值。

2.2 指针变量和普通变量有以下区别:

  1. 普通变量存储的是数据本身,而指针变量存储的是内存地址。
  2. 普通变量可以直接访问其存储的数据,而指针变量需要通过解引用运算符*来访问其指向的数据。
  3. 普通变量在声明时会自动分配内存空间,而指针变量需要使用new运算符或分配静态存储空间来动态分配内存空间。
  4. 普通变量的大小由其数据类型决定,而指针变量的大小通常是固定的,通常为4字节或8字节,具体取决于编译器和操作系统的位数。

以下是使用普通变量和指针变量的示例:

#include <iostream>
int main() {
    int x = 10;
    int* ptr = &x;

    std::cout << "Value of x: " << x << std::endl;
    std::cout << "Value of ptr: " << ptr << std::endl;
    std::cout << "Value of *ptr: " << *ptr << std::endl;

    return 0;
}

在上面的示例中,我们定义了一个名为x的整数变量,并使用取地址运算符&将其地址存储在指针变量ptr中。然后,我们使用std::cout语句输出x的值、ptr的值和*ptr的值,分别表示整数变量的值、指针变量的值和指针变量所指向的值。

3. 构造函数和拷贝构造函数

拷贝构造函数是一种特殊类型的构造函数,用于创建新对象并将其初始化为与现有对象相同的值。拷贝构造函数通常用于对象的复制和传递。当使用一个对象初始化另一个对象时,会调用拷贝构造函数。

以下是一个示例:

#include <iostream>

class A {
public:
    A() {
        std::cout << "A constructor" << std::endl;
    }

    A(const A& other) {
        std::cout << "A copy constructor" << std::endl;
    }

    ~A() {
        std::cout << "A destructor" << std::endl;
    }
};

int main() {
    A a1; // 调用构造函数

    A a2 = a1; // 调用拷贝构造函数

    return 0;
}

在上面的示例中,我们定义了一个名为A的类,并在其中定义了构造函数、拷贝构造函数和析构函数。在main()函数中,我们创建了两个A对象a1a2,分别使用构造函数和拷贝构造函数进行初始化。这将调用A类的拷贝构造函数来创建a2对象,并将a1对象的值复制到a2对象中。

3.1 简要说明构造函数和析构函数调用时机

普通变量之间赋值 会调用拷贝构造函数,在函数运行完时,会回收资源,遵循先构造 后释放的原则,如下下图:

#include <iostream>
class A {
public:
    A() {
        std::cout << "A constructor" << std::endl;
    }
    A(const A& other) {
        std::cout << "A copy constructor" << std::endl;
    }
    ~A() {
        std::cout << "A destructor" << std::endl;
    }
};

A foo(A a) {
    std::cout << "Inside foo()" << std::endl;
    A& b = a;
    return b;
}

int main() {
    A a1; // 调用构造函数
    A a2 = a1; // 调用拷贝构造函数

    foo(a2); // 调用拷贝构造函数

    return 0;
}

如果使用指针指向的对象是通过new运算符动态分配的内存,那么在不释放该内存的情况下,该内存将一直存在,直到程序结束。指针指向的对象不会自动被释放。

例如,以下代码中动态分配的整数数组不会自动被释放:

int* arr = new int[10];

如果不使用delete[]运算符来释放该数组,则该数组将一直存在,直到程序结束。

需要注意的是,在C++11及以上版本中,可以使用智能指针(如std::unique_ptrstd::shared_ptr)来管理动态分配内存,从而避免内存泄漏和手动释放内存的问题。智能指针会在对象不再需要时自动释放所占用的内存,从而提高程序的安全性和可维护性。

以下是使用std::unique_ptrstd::shared_ptr管理动态分配内存的示例:

#include <iostream>
#include <memory>

int main() {
    std::unique_ptr<int[]> arr1(new int[10]); // 使用 std::unique_ptr 管理动态分配的数组

    std::shared_ptr<int[]> arr2(new int[10]); // 使用 std::shared_ptr 管理动态分配的数组

    return 0;
}

在上面的示例中,我们使用std::unique_ptrstd::shared_ptr分别管理动态分配的整数数组。当arr1arr2不再需要时,它们会自动释放所占用的内存。

3.2 拷贝构造函数调用时机

拷贝构造函数是在以下情况下被调用:

  1. 使用一个对象初始化另一个对象时,如A a1; A a2 = a1;

  2. 将一个对象作为参数传递给函数时,如void foo(A a) { ... }

  3. 在函数中返回一个对象时,如A foo() { ... return a; }

  4. 一个对象构造另外一个对象,如A a1(10); A a2(a1,3);

4. 引用和指针的区别

在C++中,引用和指针都是用于访问内存地址的机制,但它们有以下区别:

  1. 引用是一个别名,指针是一个变量。引用在定义时必须初始化,而指针可以在任何时候指向不同的对象。
  2. 引用不能为NULLnullptr,而指针可以为NULLnullptr,表示未指向任何对象。
  3. 在函数中传递引用参数可以避免复制对象的开销

以下是使用引用和指针的示例:

#include <iostream>

void foo(int& x, int* ptr) {
    x++;
    (*ptr)++;
}

int main() {
    int x = 10;
    int* ptr = &x;
    int& x1 = x;
    std::cout << "Value of x before: " << x << std::endl;
    std::cout << "Value of ptr before: " << *ptr << std::endl;

    foo(x1, ptr);

    std::cout << "Value of x after: " << x << std::endl;
    std::cout << "Value of ptr after: " << *ptr << std::endl;

    return 0;
}
注意点:
int* arr = new int[10];
// 释放数组
delete[] arr;

delete[] arr 释放数组,不能使用 delete arr,delete运算符只会释放数组的第一个元素,而不是整个数组

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值