【C++注意事项】5 Top-level const , The auto and decltype Type Specifier

本文深入探讨了C++中常量指针的概念,区分了顶级常量与低级常量,并介绍了如何使用auto和decltype类型推导符来简化变量声明过程。通过实例展示了不同情况下auto和decltype的行为差异。

top-level const

As we’ve seen, a pointer is an object that can point to a different object. As a result, we can talk independently about whether a pointer is const and whether the objects to which it can point are const. we use the top-level const to indicate that the pointer itself is a const. When a pointer can point to a const object, we refer to that const as a low-level const.

More generally, top-level const indicates that an object itself is const. Top-level const can appear in any object type,i.e., one of the built-in arithmetic types, a class type, or a pointer type. Low-level const appears in the base type of compound types such as pointer or reference. Note that pointer types, unlike most other type, can have both top-level and low-level const independently:

int i= 0;
int *const p1= &i;  // we can't change the value of p1;const is top-level
const int ci= 42;  // we can't change ci;const is top-level
const int *p2= &ci;  // we can't change p2;cosnt is low-level
const int *const p3= p2;  // right-most const is top-level,left-most is not
const int &r= ci;  // const in reference types is always low-level

The auto Type Specifier

It is not uncommon to want to store the value of an expression in a variable. To declare the variable, we have to know the type of that expression. When we write a program, it can be surprisingly difficult–and sometimes even impossible–to determine the type of an expression. Under the new standard, we can let the compiler figure out the type for us by using the auto type specifier. Unlike type specifiers, such as double, that names a specifier type, auto tells the compiler to deduce the type from the initializer. By implication, a variable that uses auto as its type specifier must have initializer:

// the type of item is deduced from the type of the result of adding val1 and val2
auto item= val1+val2;  // item initialized to the result of vad1+vad2

Here the compiler will deduce the type of item from the type returned by applying + to val1 and val2.

First, as we’ve seen, when we use a reference, we are really using the object to which the reference refers. In particular, when we use a reference as in initializer, the initializer is the corresponding object. The compiler uses that object’s type for auto’s type deduction:

int i= 0; &r= i;
auto a= r;  // a is an int(r is an alias for i, which has type int)

Second, auto ordinarily ignores top-level consts. As usual in initializations, low-level consts, such as when an initializer is a pointer to const, are kept:

const int ci= i, &cr= ci;
auto b= ci;  // b is an int(top-level const in ci is dropped)
auto c= cr;  // c is an int(cr is an alias for ci whose const is top-level)
auto d= &i;  // d is an int*(& of an int object is int*)
auto e= &ci;  // e is cosnt int*(& of a const object is low-level const)

If we want the deduced type to have a top-level const, we must say so explicitly:

const auto f= ci;  // deduced type of ci is int; f has type const int

We can also specify that we want a reference to the auto-deduced type. Normal initialization rules still apply:

auto &g= ci;  // g is a const int& that is bound to ci
auto &h= 42;  // error: we can't bind a plain reference to a literal
const auto &j= 42;  // ok: we can bind a const reference to a literal

when we ask for a reference to an auto-deduced type, top-level consts in the initializer are not ignored. As usual, consts are not top-level when we bind a reference to an initializer.

When we define several variables in the same statement, it is important to remember that a reference or pinter is part of a particular declarator and not part of the base type for the declaration. As usual, the initializers must provide consitent auto-deduced types:

auto k= ci, &l= i;  // k is int; l is int&
auto &m= ci, *p= &ci;  // m is a const int&; p is a pointer to cosnt int
// error: type deduced from i is int; type deduced from &ci is const int
auto &n= i, *p2= &ci;

The decltype Type Specifier

Sometimes we want to define a variable with a type that the compiler deduces from an expression but do not want to use that expression to initialize the variable. For such cases, the new standard introduced a second type specifier, decltype, which returns the type of its operand. The compiler analyzes the expression to determine its type but does not evaluate the expression:

decltype(f()) sum= x;  // sum has whatever type f returns

Here, the compiler does not call f, but it uses the type that such a call would return as the type for sum. That is, the compiler gives sum the same type as the type that would be returned if we were to call f.

The way decltype handles top-level const and references differs subtly from the way auto does. When the expression to which we apply decltype is a variable, decltype returns the type of that variable, including top-level const and references:

cosnt int ci= 0, &cj= ci;
decltype(ci) x= 0;  // x has type const int
decltype(cj) y= x;  // y has type cosnt int& and is bound to x;
decltype(cj) z;  // error: z is reference and must be initialized

Because cj is a reference, decltype(cj) is a reference type. Like any other reference, z must be initialized.

It is worth nothing that decltype is the only context in which a variable defined as a reference is not treated as a synonym for the object to which it refers.

decltype and References

When we apply decltype to an expression that is not a variable, we get the type that expression yields.

// decltype of an expression can be a reference type
int i= 42, *p= &i, &r= i;
decltype(r+0) b;  // ok: addition yields an int; b is an (uninitialized) int
decltype(*p) c;  // error: c is int& and must be initialized

Here r is a reference, so decltype(r) is a reference type. If we want the type to which r refers, we can use r in an expression, such as r+0, which is an expression that yields a value that has a nonreference type.

On the other hand, the dereference operator is an example of an expression for which decltype returns a reference. As we’ve seen, when we dereference a pointer, we get the object to which the pointer points. Moreover, we can assign to that object. Thus, the type deduced by decltype(*p) is int&, not plain int.

Another important difference between decltype and auto is that the deduction done by decltype depends on the form of its given expression. What can be confusing is that enclosing the name of variable in parentheses affects the type returned by decltype. When we apply decltype to a variable without any parentheses, we get the type of that variable. If we warp the variable’s name in one or more sets of parentheses, the compiler will evaluate the operand as an expression. A variable is an expression that can be the left-hand side of an assignment. As a result, decltype on such an expression yields a reference:

// decltype of a parenthesized variable is always a reference
decltype((i)) d;  // error: d is int& and must be initialized
decltype(i) e;  // ok: e is an (uninitialized) int

Remember that decltype((variable))(note,double parentheses) is always a reference type, but decltype(variable) is reference type only if variable is a reference.



感谢您的访问,希望对您有所帮助。 欢迎大家关注、收藏以及评论。

我的更多博客文章:NoMasp博客导读


为使本文得到斧正和提问,转载请注明出处:
http://blog.youkuaiyun.com/nomasp


版权声明:本文为 NoMasp柯于旺 原创文章,未经许可严禁转载!欢迎访问我的博客:http://blog.youkuaiyun.com/nomasp

转载于:https://my.oschina.net/nomasp/blog/503420

基于实时迭代的数值鲁棒NMPC双模稳定预测模型(Matlab代码实现)内容概要:本文介绍了基于实时迭代的数值鲁棒非线性模型预测控制(NMPC)双模稳定预测模型的研究与Matlab代码实现,重点在于通过数值方法提升NMPC在动态系统中的鲁棒性与稳定性。文中结合实时迭代机制,构建了能够应对系统不确定性与外部扰动的双模预测控制框架,并利用Matlab进行仿真验证,展示了该模型在复杂非线性系统控制中的有效性与实用性。同时,文档列举了大量相关的科研方向与技术应用案例,涵盖优化调度、路径规划、电力系统管理、信号处理等多个领域,体现了该方法的广泛适用性。; 适合人群:具备一定控制理论基础和Matlab编程能力,从事自动化、电气工程、智能制造等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①用于解决非线性动态系统的实时控制问题,如机器人控制、无人机路径跟踪、微电网能量管理等;②帮助科研人员复现论文算法,开展NMPC相关创新研究;③为复杂系统提供高精度、强鲁棒性的预测控制解决方案。; 阅读建议:建议读者结合提供的Matlab代码进行仿真实践,重点关注NMPC的实时迭代机制与双模稳定设计原理,并参考文档中列出的相关案例拓展应用场景,同时可借助网盘资源获取完整代码与数据支持。
UWB-IMU、UWB定位对比研究(Matlab代码实现)内容概要:本文介绍了名为《UWB-IMU、UWB定位对比研究(Matlab代码实现)》的技术文档,重点围绕超宽带(UWB)与惯性测量单元(IMU)融合定位技术展开,通过Matlab代码实现对两种定位方式的性能进行对比分析。文中详细阐述了UWB单独定位与UWB-IMU融合定位的原理、算法设计及仿真实现过程,利用多传感器数据融合策略提升定位精度与稳定性,尤其在复杂环境中减少信号遮挡和漂移误差的影响。研究内容包括系统建模、数据预处理、滤波算法(如扩展卡尔曼滤波EKF)的应用以及定位结果的可视化与误差分析。; 适合人群:具备一定信号处理、导航定位或传感器融合基础知识的研究生、科研人员及从事物联网、无人驾驶、机器人等领域的工程技术人员。; 使用场景及目标:①用于高精度室内定位系统的设计与优化,如智能仓储、无人机导航、工业巡检等;②帮助理解多源传感器融合的基本原理与实现方法,掌握UWB与IMU互补优势的技术路径;③为相关科研项目或毕业设计提供可复现的Matlab代码参考与实验验证平台。; 阅读建议:建议读者结合Matlab代码逐段理解算法实现细节,重点关注数据融合策略与滤波算法部分,同时可通过修改参数或引入实际采集数据进行扩展实验,以加深对定位系统性能影响因素的理解。
本系统基于MATLAB平台开发,适用于2014a、2019b及2024b等多个软件版本,并提供了可直接执行的示例数据集。代码采用模块化设计,关键参数均可灵活调整,程序结构逻辑分明且附有详细说明注释。主要面向计算机科学、电子信息工程、数学等相关专业的高校学生,适用于课程实验、综合作业及学位论文等教学与科研场景。 水声通信是一种借助水下声波实现信息传输的技术。近年来,多输入多输出(MIMO)结构与正交频分复用(OFDM)机制被逐步整合到水声通信体系中,显著增强了水下信息传输的容量与稳健性。MIMO配置通过多天线收发实现空间维度上的信号复用,从而提升频谱使用效率;OFDM方案则能够有效克服水下信道中的频率选择性衰减问题,保障信号在复杂传播环境中的可靠送达。 本系统以MATLAB为仿真环境,该工具在工程计算、信号分析与通信模拟等领域具备广泛的应用基础。用户可根据自身安装的MATLAB版本选择相应程序文件。随附的案例数据便于快速验证系统功能与性能表现。代码设计注重可读性与可修改性,采用参数驱动方式,重要变量均设有明确注释,便于理解与后续调整。因此,该系统特别适合高等院校相关专业学生用于课程实践、专题研究或毕业设计等学术训练环节。 借助该仿真平台,学习者可深入探究水声通信的基础理论及其关键技术,具体掌握MIMO与OFDM技术在水声环境中的协同工作机制。同时,系统具备良好的交互界面与可扩展架构,用户可在现有框架基础上进行功能拓展或算法改进,以适应更复杂的科研课题或工程应用需求。整体而言,该系统为一套功能完整、操作友好、适应面广的水声通信教学与科研辅助工具。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值