浅谈const变量赋值报错分析

从变量到常量的赋值是合法C++的语法约定的,

如从char 到const char顺畅;
但从char **到 const char **编译器就会报错:

代码如下:

error: invalid conversion from `char**' to `const char**'

示例:

int main(int argc, char *argv[])
{
  char a = '1';
  const char b = a;

  char * a2 = "12345";
  const char * b2 = a2;

  char** a3 = NULL;

  //const char** b3 = a3; //error
   char** const c3 = a3; //ok
   char* const * d3 = a3; //ok
}

原因:

const char** b3 说明 b3的指针可以变更,可以再指向另外一个地址;
b3和a3都是unqualified的,但b3指向的对象类型为pointer to const char,
a3指向的对象类型为 pointer to char,两者是不相容类型,
不符合两操作数必须指向相容类型的规定,因此赋值非法。
更详细的解释详见参考资料1;

而char** const c3 = a3;正确,则是因为const限制了c3指针的地址变更,即它指向了a3,就不再能变更指向其它指针了;这就限制了指针地址变更可能发生的潜在问题;

当然这时候,使用一个强制类型转换,可以解决这个编译错误:

代码如下:

const char** b3 = const_cast<const char**>(a3); // ok

但转换后的代码再出现问题就很难排查了;

强制类型转换的潜在问题

看以下示例:

class Foo {
public:
 Foo(){
   i = 1;
 }
 void modify(){// make some modification to the this object
   i = 2;
 }
 void print() const {
   cout << "Foo_i:" << i << endl;
 }
private:
 int i;
};

//演示潜在的危险
//error: invalid conversion from `Foo**' to `const Foo**'
/////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
  const Foo x;
  Foo* p;

  //const Foo ** q = &p; //q now points to p; this is (fortunately!) an error
  const Foo ** q = const_cast<const Foo **>(&p);
  *q = &x; // p now points to x
  p->modify(); // Ouch: modifies a const Foo!!
  x.print(); // print: Foo_i:2
  return 0;
}

我们定义了一个常量的Foo,常量Foo方法打印出来的永远为1;

Foo**到const Foo **的转换报错,

通过一个强转符让编译通过,

最后的x.print()的结果是2;这样的潜在危险在正式的项目代码中就很难发现;

很难会想到一个const对象还能够变更;

以上所述就是本文的全部内容了,希望大家能够喜欢。

(0)

相关推荐

  • c++中const的使用详解

    Const 是C++中常用的类型修饰符,常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的. 1.定义常量(1)const修饰变量,以下两种定义形式在本质上是一样的.它的含义是:const修饰的类型为TYPE的变量value是不可变的. TYPE const ValueName = value;      const TYPE ValueName = value; (2)将const改为外部连接,作用于扩大至全局,编译时会分配内存,并且可以不进行初始化,仅仅作为声

  • C++中const用法小结

    const在C++中使用十分广泛,不同位置使用的意义也不尽相同,所以想写篇文章对其做一个总结. 首先,明确const是"不变"这个基本意义,但是不变不意味着什么都不变,下面将会看到. 1. const与变量 基本原则:const变量(对象)不能被修改 const在变量中的引入和魔数有关,所谓"魔数"指的是突然出现的一个常量值(也叫字面值常量). for(int i = 0; i < 512; i++) { // todo } 上例中,512即为魔数,512突然

  • C++类中的static和const用法实例教程

    static和const是C++程序设计中非常重要的概念,本文实例列举了C++类中的static和const的规则和用法.供大家参考借鉴.具体说明如下: 首先以代码用来举例说明.示例代码如下: class A { public: A():m(10) //const成员必须在构造函数的初始化构造列表中初始化 { q = 40; } void fun1()const { m++; //错误.const成员是常量,不能改变其值. n++; //正确.static变量n属于类,但是每个对象的函数都可以访

  • C++中const的用法详细总结

    1. const修饰普通变量和指针 const修饰变量,一般有两种写法: const TYPE value;TYPE const value; 这两种写法在本质上是一样的.它的含义是:const修饰的类型为TYPE的变量value是不可变的. 对于一个非指针的类型TYPE,无论怎么写,都是一个含义,即value只不可变. 例如: const int nValue: //nValue是constint const nValue: // nValue是const 但是对于指针类型的TYPE,不同的写

  • c++ 类中const成员变量的赋值方法

    在头文件的类的定义中定义了一个const成员变量c++ 规则: 1.类定义中不能进行初始化,因为头文件中类的定义只是一个声明,并没有分配真正空间,因此变量是不存在的,因此是不能赋值的. 2.const 定义的变量是不能赋值 这可如何是好,声明中不能赋值,声明完还不能赋值.又不能不赋值. 解决方案: 1.在构造函数后的参数初始化列表中初始化 2.将const变量同时声明为 static 类型进行初始化. Eg: #include <iostream> class CTestA { public:

  • 浅谈const变量赋值报错分析

    从变量到常量的赋值是合法C++的语法约定的, 如从char 到const char顺畅: 但从char **到 const char **编译器就会报错: 复制代码 代码如下: error: invalid conversion from `char**' to `const char**' 示例: int main(int argc, char *argv[]) { char a = '1'; const char b = a; char * a2 = "12345"; const

  • 浅谈vue的第一个commit分析

    为什么写这篇vue的分析文章? 对于天资愚钝的前端(我)来说,阅读源码是件不容易的事情,毕竟有时候看源码分析的文章都看不懂.每次看到大佬们用了1-2年的vue就能掌握原理,甚至精通源码,再看看自己用了好几年都还在基本的使用阶段,心中总是羞愧不已.如果一直满足于基本的业务开发,怕是得在初级水平一直待下去了吧.所以希望在学习源码的同时记录知识点,可以让自己的理解和记忆更加深刻,也方便将来查阅. 目录结构 本文以vue的第一次 commit a879ec06 作为分析版本 ├── build │ └─

  • 浅谈静态变量、成员变量、局部变量三者的区别

    静态变量和成员变量的区别: A:所属不同 静态变量:属于类,类变量    成员变量:属于对象,对象变量,实例变量 B:内存位置不同 静态变量:方法区的静态区    成员变量:堆内存 C:生命周期不同 静态变量:静态变量是随着类的加载而加载,随着类的消失而消失    成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失 D:调用不同 静态变量:可以通过对象名调用,也可以通过类名调用    成员变量:只能通过对象名调用 成员变量和局部变量的区别: A:在类中的位置不同 成员变量:在类中方法

  • 浅谈JavaScript变量的自动转换和语句

    JS自动类型转换 var a = 1; var b = true; "==" 表示 可以自动类型转换,比较的是数值  "===" 表示可以自动类型转换,先比较数值,再比较类型 if (a == b) { alert("相等"); //打印 }else{ alert("不等"); } 三目运算 var c = 10/2 > 4 ? 5 : 3 ; alert(c); 关于for循环 for ( var i = 0; i &

  • 解决Vue 给mapState中定义的属性赋值报错的问题

    1. 实践环境 Vue 2.9.6 2. 问题描述 <script> import { mapState } from 'vuex'; export default { name: "displayCount", computed: { ...mapState({ ...略 count: state => state.a.count }) }, methods: { increaseCount () { this.count = this.count + 1 } }

  • 浅谈MySQL为什么会选错索引

    目录 1.引例 2.优化器的逻辑 3.解决办法 1.引例 首先创建一张表,并对字段a,b分别建立索引: create table t ( id int(11) not null, a int(11) default null, b int(11) default null, primary key (id), key a(a), key b(b) )engine=InnoDB; 然后往表中,插入十万行数据,值按整数递增:(1,1,1).(2,2,2).(3,3,3)… delimiter ;;

  • 浅谈go语言renderer包代码分析

    renderer是Go语言的一个简单的.轻量的.快速响应的呈现包,它可以支持JSON.JSONP.XML.HYAML.HTML.File等类型的响应.在开发web应用或RESTFul API的时候,这个包是非常方便的toolkit. 本文绕开如何使用它,深入到代码实现中研究它,同时也尝尝Go语言包的开发套路. Go包基础介绍 代码结构 package pkgname import ( "fmt" ... ) const ( CONST1 typeX = xx ... ) var ( V

  • 浅谈关于JavaScript的语言特性分析

    前言在JavaScript中,作用域.上下文.闭包.函数等算是精华中的精华了.对于初级JSer来说,是进阶必备.对于前端攻城师来说,只有静下心来,理解了这些精华,才能写出优雅的代码. 本文旨在总结容易忘记的重要知识,不会讲基本的概念.如果对基本知识不太熟悉,就去翻下< JavaScript权威指南>吧~ 语言特性函数表达式 先看代码段: 复制代码 代码如下: [javascript] view plaincopyprint?var f = function foo(){      return

  • 浅谈页面装载js及性能分析方法

    一.装载 先装载静态页面的引用js文件,然后查找引用文件中是否包含onload函数,比如main.js中包含onload函数,在main.js中查找是否有对其他js文件的引用,优先装载引用js文件,被引用中文件的装载顺序和main.js的顺序一致. 装载完毕后,开始执行onload函数.由于js执行顺序是顺序执行的,为提高页面相应速度,一般做法是在onload中只画页面,一些事件的绑定函数,ajax方法等可延后书写. 二.响应速度分析 1.借助工具进行分析 各大浏览器的开发者工具(最喜欢使用火狐

  • Python编程之变量赋值操作实例分析

    本文实例讲述了Python编程之变量赋值操作.分享给大家供大家参考,具体如下: #coding=utf8 ''''' Python中主要通过等号(=)进行赋值. Python中的赋值不是直接将一个值赋给一个变量, 而是将该对象的引用(并不是值)赋值给变量. ''' #赋值运算符 Int=12 Float=12.2 String="hello" List=[1,2,"hell"] Touple=(4,"hell") Dictionary={'one

随机推荐