首页 > 编程语言 >C++学习1 “&”符号的用法

C++学习1 “&”符号的用法

时间:2024-07-03 10:23:50浏览次数:14  
标签:std const 函数 符号 C++ 用法 vector 引用 vec

“单纯来源于CHATGPT”

在 C++ 中,& 符号具有多重用途,主要包括以下几种情况:

1. 地址运算符

& 用于变量前面时,它作为一种一元运算符,用来获取该变量在内存中的地址。例如:

int a = 5;
int* p = &a; // p 存储 a 的内存地址

这里 &a 表示变量 a 的地址。

2. 引用声明

在类型声明中,& 用来定义引用类型。引用是一个别名,指向另一个已存在的变量。与指针不同,引用一旦被初始化后,就不能更改其绑定到另一个对象。

int x = 10;
int& ref = x; // ref 是 x 的引用
ref = 20; // 现在 x 也为 20

这里 int& ref = x; 定义了一个整型的引用 ref,它指向 x

3. 按位与运算符

& 还可以用作按位与运算符,用于对二进制表示的整数进行操作,只有对应的两个位都为 1 时,结果位才为 1。例如:

int result = 5 & 3; // 等于 1

分析:5 的二进制是 1013 的二进制是 011,两者进行按位与操作得到 001,即十进制中的 1

4. 取地址和解引用运算符(仅在 C++11 或更高版本)

在 C++11 或更高版本中,&& 可以用于声明右值引用,这是对传统引用的扩展,允许引用临时对象:

void function(int&& x) {
    // x 是一个右值引用
}

这里 int&& x 表示 x 是一个绑定到右值的引用。右值引用主要用于实现移动语义和完美转发。

5. 逻辑与运算符

虽然逻辑与运算符是两个 &&,但它与 & 的概念相关。它用于布尔逻辑,当两侧的操作数都为真时返回真。

bool result = true && false; // 结果为 false

在 C++ 中,使用 & 来定义常量引用是一种非常常见且有用的做法。常量引用主要用于以下目的:

1. 传递参数给函数

当你希望通过函数传递一个大型对象但又不希望因复制而产生额外开销时,引用非常有用。使用常量引用可以确保:

  • 传递的对象不会被函数修改(保护数据安全)。
  • 不会因为复制对象而产生额外的性能成本。

示例:

void printVector(const std::vector<int>& vec) {
    for (int num : vec) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}

在这个例子中,const std::vector<int>& vec 是一个常量引用,它允许函数 printVector 读取传入的向量,但不能修改它。如果没有 const,函数内部将可以修改向量的内容。如果没有使用引用,向量将会被复制,这对于大型向量来说可能是成本高昂的。

2. 返回函数结果

常量引用也常用于从函数返回一个对象的引用而不进行复制。这可以提高效率,但必须小心确保返回的引用不是指向局部变量的引用,因为局部变量在函数结束时会被销毁。

示例:

const std::string& getStatus() {
    static std::string status = "Complete";
    return status;
}

这里,getStatus 函数返回一个静态局部字符串的常量引用。由于 status 是静态的,它在函数调用结束后依然存在,因此返回它的引用是安全的。

3. 用作类成员

在类设计中,常量引用可以用作类成员,来引用在类外部定义的对象,同时保证不会在类的方法中被修改。

示例:

class Example {
private:
    const int& ref;
public:
    Example(const int& r) : ref(r) {}
    void print() const {
        std::cout << "The reference value is: " << ref << std::endl;
    }
};

在这个例子中,Example 类包含一个对整数的常量引用。这个引用在构造函数中初始化,并且类中的方法不能修改它所引用的值。

重要注意事项

使用常量引用时,需要确保它引用的对象在引用期间持续存在。如果引用的对象在引用还在使用时被销毁,将导致未定义行为(例如,引用悬挂)。

常量引用是 C++ 中提高程序效率和安全性的重要工具,通过减少不必要的对象复制并保护数据不被无意修改,它在许多场合都非常有用。

在 C++ 中,函数定义 void printVector(const std::vector<int>& vec) 中的 & 符号表示 vec 是对一个 std::vector<int> 类型的引用。这里的 & 符号用于创建一个引用,具体是一个常量引用(const 关键字的存在意味着这个引用是常量的),这意味着通过这个引用可以访问传递给函数的原始 std::vector<int> 对象,但不能修改它。

使用常量引用的优点包括:

  1. 避免拷贝

    • 当你向函数传递一个大的数据结构或对象(如 std::vector)时,如果不使用引用,则会创建该数据的一个副本。这个过程可以消耗大量的时间和内存,特别是当数据结构包含大量数据时。
    • 使用引用,函数将直接操作原始数据,不会发生复制。这使得程序更高效。
  2. 数据保护

    • const 关键字保证了函数内部不会(也不能)修改被引用的数据。这提供了一种安全保障,确保数据在函数执行过程中保持不变。
    • 这对于维护程序的正确性和预测性非常重要,因为你可以确信数据不会被意外改变。

示例详解:

printVector 函数中,const std::vector<int>& vec 的意思是:

  • vec 是对一个 std::vector<int> 的引用,所以传递给函数的是原始向量的引用,而不是其副本。
  • const 确保了这个向量在 printVector 函数内部不会被修改。函数可以读取向量的内容,例如遍历元素或获取其大小,但不能修改向量中的元素、添加新元素或做其他任何修改操作。

这种方式是处理大型数据结构的标准做法,尤其是在需要读取或检查数据而不需要修改时。这样不仅提高了效率,还增强了函数的通用性和安全性。

如果在 printVector 函数的参数中省略了 & 符号,那么函数的行为将有显著不同。参数变为传值而非传引用。具体地:

定义变化

原来的函数定义:

void printVector(const std::vector<int>& vec)

如果去掉了 &,则变为:

void printVector(const std::vector<int> vec)

影响和结果

  1. 性能影响

    • 拷贝开销:去掉 & 后,vec 参数会通过复制原始向量的方式传入函数,而不是通过引用。对于大型向量来说,这个复制操作可能会导致显著的性能损失,因为每次函数调用都会创建向量的一个完整副本。
    • 内存使用:复制会增加程序的内存使用,尤其是当向量包含大量数据时。
  2. 功能影响

    • 尽管参数声明中包含 const 关键字,确保函数内部不能修改向量,但因为是传值,函数内部对 vec 的任何修改都不会影响原始向量。这在某些情况下可能是所希望的行为,但通常在此类场景下,目的是读取而不改变数据。
  3. 设计和用途

    • 数据安全性:虽然传值方式意味着原始数据不会被修改(因为操作的是数据的副本),但这种安全性是以牺牲性能为代价的。
    • 适用性:如果你确实需要一个函数的本地副本并计划在函数内部对其进行修改,而这些修改不应影响外部数据,传值可能是合适的。但在大多数读取操作中,使用传引用更为高效。

结论

如果函数仅仅是为了读取数据而不进行修改,最佳实践是使用 const 修饰的引用参数(即 const std::vector<int>&),这样既保证了数据的不可修改性,也避免了不必要的数据复制。从性能和内存效率的角度考虑,特别是处理大型数据结构如 std::vector 时,应优先考虑使用引用。这种做法在C++社区中广泛被接受,是处理大型集合数据的标准方式。

标签:std,const,函数,符号,C++,用法,vector,引用,vec
From: https://www.cnblogs.com/HumbleHater/p/18281075

相关文章

  • C++11——新特性超详细总结
    目录一、C++11介绍二·、为什么要用C++11三、新特性总结1、类型推导(auto/decltype)2、序列for循环语句3、lamdba表达式4、构造函数:委托构造和继承构造5、容器(array/forward_list)6、垃圾回收机制7、正则表达式基础7.1、符号7.2、速记理解技巧7.3、检验数字的表达式......
  • 【C++】多态(定义、虚函数、重写、隐藏)
      ......
  • C/C++ sizeof 运算符注意事项
    sizeof 运算符在C/C++中用于获取变量或类型所占的内存大小(以字节为单位)。尽管 sizeof 是一个相对简单直接的运算符,但在使用时还是需要注意一些细节和特殊情况,以避免误解或错误。以下是一些使用 sizeof 运算符时需要注意的事项:数据类型大小:sizeof 返回的是变量或类型在......
  • Qt/C++编写地图应用/离线地图下载/路径规划/轨迹回放/海量点/坐标转换
    一、前言说明这个地图组件写了很多年了,最初设计的比较粗糙,最开始只是为了满足项目需要,并没有考虑太多拓展性,比如最初都是按照百度地图写死在代码中,经过这几年大量的现场实际应用,以及大量的用户提出的改进意见,逐渐萌生了彻底重新编写对应地图相关的代码,比如基类子类的设计,各种功能......
  • C++ STL 优先队列 (priority_queue)
    std::priority_queue<queue>优先队列  1、第一个元素始终为最大元素。  2、有着类似于堆的特性,它可以在其中随时插入元素。  3、支持下标访问(随机访问迭代器)优先队列内部的实现需要依赖基础容器,该容器应可通过随机访问迭代器访问,并需要支持以下操作empty()si......
  • 【C++ | 继承】|概念、方式、特性、作用域、6类默认函数
    继承1.继承的概念与定义2.继承的方式2.1继承基本特性2.2继承的作用域2.2.1隐藏赋值兼容派生类的创建和销毁构造函数拷贝构造赋值重载1.继承的概念与定义继承是面向对象编程中的一个重要概念。它的由来可以追溯到软件开发中的模块化设计和代码复用的需求。在软件......
  • MyBatis的几个核心类和基本用法
    1.SqlSessionFactoryBuilder:读取配置信息创建SqlSessionFactory,建造者模式,方法级别生命周期,方法结束生命周期结束;重点是建造出SqlSessionFactory工厂对象2.SqlSessionFactory:SqlSession工厂对象,用于创建Sqlsession,工厂单例模式,存在于程序的整个生命周期;3.SqlSession:代......
  • C++字体库开发
    建议根据字体需求,多个组合使用。高度定制可基于freeType+harfbuzz基础库完成。GitHub-GNOME/pango:Read-onlymirrorofhttps://gitlab.gnome.org/GNOME/pangoGitHub-googlefonts/fontview:Demoappthatdisplaysfontswithafree/libre/open-sourcetextrenderi......
  • timezone包的用法
    文章目录1.概念介绍2.使用方法2.1获取所有时区2.2转换时区时间3.示例代码4.内容总结我们在上一章回中介绍了"分享一些好的Flutter站点"相关的内容,本章回中将介绍timezone包.闲话休提,让我们一起TalkFlutter吧。1.概念介绍我们在前面章回中介绍了获取当前......
  • 车站选票代码分析与展示(C++版)
    目录程序的主要功能1.主窗口:2.管理员窗口:3.普通顾客窗口:主要数据结构函数间调用关系算法流程图1.查询算法流程图​编辑2.乘客买票算法流程图程序运行结果1.主窗口->管理员窗口a.管理员窗口->验证窗口b.管理员增加车次信息c.浏览全部车辆信息d.注销车次信息e.车......