当前位置: 首页 > news >正文

C++高频知识点(三)

文章目录

  • 11. 请解释const关键字在C++中的作用
  • 12. 解释浅拷贝和深拷贝,并提供相应代码示例。
    • 浅拷贝示例:
    • 深拷贝示例:
  • 13. 解释指针与数组之间的关系,如何通过指针遍历数组?
  • 14. 解释auto关键字在C++11中的作用及其使用场景。
  • 15. 什么是移动语义(Move Semantics)?它有什么优势?

11. 请解释const关键字在C++中的作用

const 关键字在 C++ 中有多种用途,主要用于定义常量或确保某些变量的值不被修改。以下是 const 在 C++ 中的一些主要用途:

  1. 定义常量:const 可以用来定义常量,即其值在程序运行过程中不可改变的量。例如:
const int a = 10;

这里,a 是一个常量,其值被设定为 10,并且不能在程序运行过程中被修改。

  1. 指针与 const:const 在指针的使用中特别有用,可以用它来保证指针指向的内容不被修改,或者保证指针本身的值(即内存地址)不被修改,或者两者都不被修改。
  • 指向常量的指针(指针指向的内容不能被修改)
const int *p = &a;
  • 常量指针(指针本身的值不能被修改)const的右边 离谁最近 就是修饰谁
    这里,p 是一个指针,它指向一个常量整数。你不能通过 p 来修改它所指向的值。
int b = 20;  
int *const q = &b;

这里,q 是一个常量指针,指向一个整数。你不能改变 q 的值(即它不能指向其他地址),但可以通过 q 来修改它所指向的内容。

  1. 函数参数与 const:在函数参数中使用 const 可以保证传递给函数的参数在函数体内不会被修改,从而增强代码的可读性和安全性。例如:
int CalculateSomething(const int &a, const int& b) {  // ... do something ...  
}

在这个函数中,a 和 b 的值都不能被修改。

  1. const 成员函数:在类的成员函数声明后面添加 const 关键字,表示这个成员函数不会修改类的任何成员变量(除了被声明为 mutable 的成员)。这有助于确保成员函数不会意外地修改对象的状态。例如:
class MyClass {  
public:  int GetValue() const {  return value_;  }  
private:  int value_;  
};

在这个例子中,GetValue 函数是一个常量成员函数,它保证不会修改 MyClass 的任何成员变量。

  1. constexpr:C++11 引入了 constexpr 关键字,它用于在编译时计算常量表达式的值。这与 const 相似,但 constexpr 强调表达式的值在编译时就是已知的。例如:
constexpr int x = 2 * 3; // x 在编译时就被计算为 6

12. 解释浅拷贝和深拷贝,并提供相应代码示例。

在C++中,浅拷贝和深拷贝是关于对象复制的重要概念。
浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果字段是基本数据类型,那么对该字段执行逐位拷贝。如果字段是引用类型(例如指针或引用),则拷贝引用但不拷贝引用的对象。因此,原始对象及其副本引用同一个对象。
深拷贝:将对象复制到另一个对象中,同时递归地复制对象中的引用类型的属性。这意味着,如果原对象内部的子对象发生变化,不会影响到已经复制出去的对象。
下面,我们分别用代码示例来解释浅拷贝和深拷贝:

浅拷贝示例:

#include <iostream>  
#include <bits/stdc++.h>class StringShallowCopy {
public:char* str;// 构造函数  StringShallowCopy(const char* s = "") {if(s) {str = new char[strlen(s) + 1];strcpy(str, s);} else {str = nullptr;}}// 拷贝构造函数 - 浅拷贝  StringShallowCopy(const StringShallowCopy& other) {// 注意,这里只是简单地拷贝了指针,没有拷贝指针指向的内容  str = other.str;}~StringShallowCopy() {delete[] str;}void print() {std::cout<< str<< std::endl;}
};int main() {StringShallowCopy s1{"Hello"};// 使用拷贝构造函数进行浅拷贝StringShallowCopy s2{s1};s2.print();// 这里会出现问题,因为s1和s2的str指向同一块内存,当s1析构时会释放这块内存,  // 然后s2析构时会再次尝试释放同一块内存,导致未定义行为(通常是程序崩溃)return 0;
}

在这里插入图片描述
注意:上面的浅拷贝示例中,析构函数会导致问题,因为两个对象的str成员指向同一块内存。在实际编程中,应避免这种情况。

深拷贝示例:

#include <iostream>  
#include <cstring>  class StringDeepCopy {
public:char* str;// 构造函数StringDeepCopy(const char* s = "") {if(s) {str = new char[strlen(s) + 1];strcpy(str, s);} else {str = nullptr;}}// 拷贝构造函数 - 深拷贝StringDeepCopy(const StringDeepCopy& other) {if(this != &other) { // 防止自我赋值if(other.str) {str = new char[strlen(other.str) + 1];strcpy(str, other.str);} else {str = nullptr;}}}~StringDeepCopy() {delete[] str; // 释放内存}   void print() {std::cout << str<< std::endl;}
};int main() {StringDeepCopy s1{"Hello"};StringDeepCopy s2{s1}; // 调用拷贝构造函数进行深拷贝s2.print();// 这里没有问题,因为s1和s2的str指向不同的内存块return 0;
}

在这里插入图片描述

在上面的深拷贝示例中,StringDeepCopy类的拷贝构造函数为str成员分配了新的内存,并将原始字符串的内容复制到新内存中。这样,每个对象都有自己的str副本,互不影响。

13. 解释指针与数组之间的关系,如何通过指针遍历数组?

指针和数组在C/C++语言中有着紧密的关系。简单来说,数组名可以被看作是指向数组第一个元素的指针。这种关系使得我们可以通过指针来访问和遍历数组。

在这里插入图片描述

#include <stdio.h>  int main() {  int arr[] = {1, 2, 3, 4, 5};  int *p = arr;  // 指针p指向数组的第一个元素  int i;  for (i = 0; i < 5; i++) {  printf("%d ", *(p + i));  // 使用指针算术来访问数组元素  }  printf("\n");  // 或者,你也可以这样遍历数组:  for (p = arr; p < arr + 5; p++) {  printf("%d ", *p);  // 通过解引用指针p来访问当前指向的元素  }  printf("\n");  return 0;  
}

在这里插入图片描述

14. 解释auto关键字在C++11中的作用及其使用场景。

在C++11中,auto关键字被引入用于自动类型推导,即让编译器根据初始化表达式自动推导出变量的类型。这一特性极大地简化了代码书写,减少了类型声明的繁琐性,同时也增强了代码的可读性和可维护性。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

15. 什么是移动语义(Move Semantics)?它有什么优势?

在这里插入图片描述

下面是一个简单的代码样例,展示了如何使用std::move来移动一个std::string对象:

#include <iostream>  
#include <string>  
#include <utility> // 为了使用 std::move  class MyString {
public:MyString(const std::string&s): data(new std::string(s)) {}// 移动构造函数MyString(MyString&& other) noexcept: data(other.data) {other.data = nullptr; // 将源对象的指针置为nullptr,避免析构时释放内存}// 移动赋值运算符MyString& operator=(MyString&& other) noexcept {if(this != &other) {delete data; // 释放当前对象的内存data = other.data; // 转移资源other.data = nullptr; // 将源对象的指针置为nullptr,避免析构时释放内存}return *this;}// 析构函数~MyString() {delete data; // 释放内存}std::string& getdata() const{return *data; // 返回字符串数据}private:std::string* data; // 使用指针来管理字符串数据
};int main() {MyString s1("Hello, World!");MyString s2 = std::move(s1); // 使用移动赋值运算符转移资源// 此时s1的资源已经被移动到s2,所以s1现在是一个空对象(或无效对象)  // 尝试访问s1可能会导致未定义行为  // 注意:在实际应用中,你应该避免在移动后使用s1,除非你确定它是安全的  // 输出s2以验证资源已经被移动  std::cout<< s2.getdata()<< std::endl;return 0;
}

在这里插入图片描述

在这里插入图片描述

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

http://www.dtcms.com/a/268570.html

相关文章:

  • 基于STM32设计的心率脉搏测量仪(项目资料)(ID:9)
  • 【Linux | 网络】网络编程套接字
  • Baklib作为赞助商参加RubyConf China 2025 技术大会
  • Java基础:随机数生成、循环结构与方法封装详解
  • 国产MCU学习Day10——CW32F030C8T6模拟电压比较器全解析
  • 【EGSR2025】材质+扩散模型+神经网络相关论文整理随笔
  • springsecurity03--异常拦截处理(认证异常、权限异常)
  • 【机器学习深度学习】多分类评估策略:混淆矩阵计算场景模拟示例
  • Rust 注释
  • OpenAI要开发能聊天的AI版Office挑战微软?
  • 【Spring】Spring Boot + OAuth2 + JWT + Gateway的完整落地方案,包含认证流程设计
  • window 服务器上部署前端静态资源以及nginx 配置
  • 揭秘图像LLM:从像素到语言的智能转换
  • 创意Python爱心代码
  • 基于Flink 1.20、StarRocks与TiCDC构建高效数据处理链路教程
  • linux如何下载github的一个项目
  • stm32与tp-linkv2接线、解决识别不到芯片问题
  • C++ -- string类的模拟实现
  • Go的标准库http原理解析
  • 【论文阅读】Few-Shot PPG Signal Generation via Guided Diffusion Models
  • Web Worker:让前端飞起来的隐形引擎
  • 第0章:开篇词 - 嘿,别怕,AI应用开发没那么神!
  • 【PaddleOCR】数据合成工具 Style-Text安装与使用案例介绍
  • 【机器学习笔记 Ⅲ】3 异常检测算法
  • 4D-VLA:具有跨场景标定的时空视觉-语言-动作预训练
  • Linux运维安全新范式:基于TCPIP与SSH密钥的无密码认证实战
  • 【保姆级图文详解】探秘 Prompt 工程:AI 交互的关键密码
  • C++多线程网络编程:助力高并发服务器性能提升
  • 无人机精准降落辅助系统核心技术解析
  • 一文讲清楚React Fiber