文档章节

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

NoMasp
 NoMasp
发布于 2015/09/08 21:49
字数 1408
阅读 6
收藏 0

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.csdn.net/nomasp


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

本文转载自:http://blog.csdn.net/nomasp/article/details/45896981

NoMasp
粉丝 7
博文 334
码字总数 0
作品 0
镇江
程序员
私信 提问
加载中

评论(0)

C++ Primer 学习笔记(第三章:字符串、向量和数组)

C++ Primer 学习笔记(第三章:字符串、向量和数组) [TOC] 3.1 命名空间的声明 声明语句可以一行放多条。 位于头文件的代码,一般来说不应该使用声明。因为其内容会拷贝到每个使用该头文件的...

ShawnLue
2015/08/20
164
0
C++ Primer 学习笔记(第四章:表达式)

C++ Primer 学习笔记(第四章:表达式) [TOC] 4.1 基础 左值和右值: 当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。...

ShawnLue
2015/08/20
51
0
【C++11】30分钟了解C++11新特性

---------- 点击进入我的新博客 什么是C++11 C++11是曾经被叫做C++0x,是对目前C++语言的扩展和修正,C++11不仅包含核心语言的新机能,而且扩展了C++的标准程序库(STL),并入了大部分的C++...

王选易
2013/12/10
3.4W
42
C++11 & C++14 & C++17新特性

原文:https://www.cnblogs.com/guxuanqing/p/6707824.html C++11:C++11包括大量的新特性:包括lambda表达式,类型推导关键字auto、decltype,和模板的大量改进。 新的关键字 auto C++11中引...

炎林2018
2018/12/06
0
0
C++11 FAQ中文版:decltype – 推断表达式的数据类型

C++11 FAQ中文版:decltype – 推断表达式的数据类型 二 24 Year 2011 陈 良乔 C++11 FAQ decltype – 表达式的数据类型 decltype(E)是一个标识符或者表达式的推断数据类型(“declared type...

长平狐
2013/01/11
146
0

没有更多内容

加载失败,请刷新页面

加载更多

 企业信息平台的快速搭建,框架如何选?

Web端开发框架如何选 目前,大部分的企业信息集成系统都在web端运行,而搭建框架的选择对一个企业的发展至关重要,不过其最终目的都是要符合企业发展逻辑,助力企业战略的实施。 而在框架的选...

我想造火箭
22分钟前
32
0
安装mysql 实操截图

前言: CentOS 7 版本将MySQL数据库软件从默认的程序列表中移除,用MariaDB代替了,MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可。开发这个分支的原因之...

冥焱
26分钟前
57
0
FecMall 多商户分销系统 - 价格公式计算

FecMall Fecbdc 分销价格公式计算 本章详解讲述分销平台的各个价格,以及相应的设置,本章节非常重要,贯穿分销系统的整个流程,请仔细阅读 官网: http://www.fecmall.com/ 业务逻辑设计 系...

FecShop
27分钟前
33
0
Java Web 学习笔记(7)

文件下载 package com.janeroad.servlet;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.......

JaneRoad
31分钟前
41
0
如何在JavaScript中更改span元素的文本

如果我有跨度,请说: <span id="myspan"> hereismytext </span> 如何使用JavaScript将“ hereismytext”更改为“ newtext”? #1楼 对于现代浏览器,您应该使用: document.getElementByI......

技术盛宴
33分钟前
46
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部