首页 > 其他分享 >记一次编译错误

记一次编译错误

时间:2023-07-03 13:22:04浏览次数:43  
标签:一次 错误 Derived 编译 Base 报错 pd 赋值 指针

我在照着STL 源码刨析写 STL 的时候出现了一个编译错误. 当时的情况是我要用一个派生类的指针给一个基类指针的引用赋值, 类似于:

class Base {};
class Derived : public Base {};

Derived *d = new Derived();
Base *&b = d;

但是编译器报错, 错误信息类似于:

error: cannot bind non-const lvalue reference of type ‘Base*&’ to an rvalue of type ‘Base*’

在 C++ 中, 派生类的指针可以直接给基类指针赋值以实现多态的特性. 但是却不可以给基类指针的引用赋值. 这个报错当时令我很困惑. 经过查阅并分析报错信息, 该语句的执行过程应该是首先创建了一个类型为 Base* 的临时值, 用 d 来初始化, 再把这个临时值赋予变量 b. 因为这个临时值是右值不能给左值赋值, 所有会有这个报错.

这个问题可以用两种方式解决.

第一种方式是通过常量引用可以指向右值实现的. 就是把变量 b 声明为常量指针, 即 Base * const &b = d, 这样就解决了这个问题.

但是在我当时的代码中不能通过这个方法解决. 因为报错的函数是红黑树的一个迭代函数, 有可能改变 d 的值. 这样的解决方法会复制 d 的值, 使得函数内改变的局部值无法作用到外部的 d 上.

第二种方式是先把 d 做一个强制类型转换再赋值给 b, 即 Base *&b = (Base*&)d. 这样就可以在函数中通过修改 b 的值修改 d.

下面是一个示例代码. 验证两种方法.

class Base {};
class Derived : public Base {};

Derived *pd = new Derived();
Base * const &pb1 = pd;   // 方法 1
Base *&pb2 = (Base*&)pd;  // 方法 2

cout << "addr of pd:\t" << &pd << endl;
cout << "addr of pb1:\t" << &pb1 << endl;
cout << "addr of pb2:\t" << &pb2 << endl;

编译没有报错, 运行得到下面的结果:

add of pd:	0x7ffcdec09978
add of pb1:	0x7ffcdec09980
add of pb2:	0x7ffcdec09978

说明方法 1 创建了一个新的指针, 而方法 2 绑定在原来的指针上.

标签:一次,错误,Derived,编译,Base,报错,pd,赋值,指针
From: https://www.cnblogs.com/TechThing/p/17522506.html

相关文章

  • [oeasy]python0070_动态类型_静态类型_编译_运行_匈牙利命名法
     动态类型_静态类型回忆上次内容 上次了解了帮助文档的生成开头的三引号注释可以生成帮助文档文档可以写成网页 python3本身也有在线的帮助手册 目前的程序提高了可读性   ​ 添加图片注释,不超......
  • [oeasy]python0070_动态类型_静态类型_编译_运行_匈牙利命名法
    动态类型_静态类型回忆上次内容上次了解了帮助文档的生成开头的三引号注释可以生成帮助文档文档可以写成网页python3本身也有在线的帮助手册目前的程序提高了可读性还有什么方法可以让程序更可读么?......
  • C++面试八股文:std::array如何实现编译器排序?
    C++面试八股文:std::array如何实现编译器排序?某日二师兄参加XXX科技公司的C++工程师开发岗位第25面:面试官:array熟悉吗?二师兄:你说的是原生数组还是std::array?面试官:你觉得两者有什么区别?二师兄:区别不是很大,原生数组(非动态数组)和std::array都在栈上开辟空间,初始化的时候......
  • PowerShell脚本数字签名错误
    1.以管理员身份打开powershell,使用get-executionpolicy-list查看策略设置2.将所有的scope的值为:undefined具体设置的命令是:Set-ExecutionPolicy-ExecutionPolicyundefined-ScopeLocalMachine3.找到报错中提示中有问题的xxx.ps1脚本,选中该脚本,右键选择属性,然后勾选“解......
  • 龙蜥7.9 编译安装redis
    1、下载redis安装包2、我一般放在/home下面,redis默认安装在/usr/local/bin/下面,修改目录命令为:makePREFIX=/usr/local/redisinstall#安装编译环境yum-yinstallgcc-c++autoconfautomake#开始安装cd/hometarzxvfredis-7.0.11.tar.gzcdredis-7.0.11/makemakeinsta......
  • LinuxDNS分析从入门到放弃(记一次有趣的dns问题排查记录,ping 源码分析,getaddrinfo源码
    PS:要转载请注明出处,本人版权所有。PS:这个只是基于《我自己》的理解,如果和你的原则及想法相冲突,请谅解,勿喷。环境说明  ubuntu18.04前言  我们这里有一块嵌入式板卡,当我们通过PING测试内网IP时,发现外网IP访问正常,但是测试域名访问一直报unknownhost。一般来说,在ubun......
  • tpcc客户端编译调试
    【代码地址】https://www.postgresql.org/message-id/CAGBW59f9q2Y4v-B3D8gje3xUsWz2Z-WaK9wYx4%3DhCY1zN%3D7%2BBQ%40mail.gmail.com【修改之后】根目录ant编译【执行】 【代码主要逻辑】 【客户端执行代码】......
  • ImportError:无法从“django.utils.encoding”导入名称“force text”[Python错误已解
    在软件开发过程中遇到错误是很常见的,在使用Python和Django时,这样的错误之一就是ImportError:cannotimportname'forcetext'from'django.utils.encoding'.forcetext此特定错误表明从模块导入方法时出现问题django.utils.encoding。缺少的方法用于将输入数据转换为一致......
  • 解释器和编译器
    解释器和编译器是两种不同的程序,用于处理和执行源代码。它们之间的主要区别在于代码的转换和执行方式。编译器将整个源代码文件作为输入,对其进行分析、优化和转换,并生成等价的目标代码(通常是机器码或字节码)。这个过程称为编译。生成的目标代码可以在计算机上直接执行,无需再次转换......
  • 利用ccache提高c++编译速度
    首先安装ccache:sudoaptinstallccache然后在cmake文件中添加如下代码即可:find_program(CCACHE_FOUNDccache)if(CCACHE_FOUND)set_property(GLOBALPROPERTYRULE_LAUNCH_COMPILEccache)set_property(GLOBALPROPERTYRULE_LAUNCH_LINKccache)endi......