C++ Primer 第四章 表达式

news2025/2/5 19:50:23

C++ Primer 第四章 表达式

  • 4.1. Fundamentals
    • 4.1.1. Lvalues and Rvalues
    • 4.1.2. Precedence and Associativity
  • 4.2. Arithmetic Operators
  • 4.4. Assignment Operators
  • 4.5. Increment and Decrement Operators
  • 4.9. The sizeof Operator
  • 4.10. Comma Operator
  • 4.11. Type Conversions
    • 4.11.1. The Arithmetic Conversions
    • 4.11.2. Other Implicit Conversions
      • Array to Pointer Conversions
      • Pointer Conversions
      • Conversion to const
      • Conversions Defined by Class Types
    • 4.11.3. Explicit Conversions
      • Named Casts
        • static_cast
        • const_cast
        • reinterpret_cast
      • Old-Style Casts
  • 4.12. Operator Precedence Table

4.1. Fundamentals

4.1.1. Lvalues and Rvalues

  • Every expression in C++ is either an rvalue or an lvalue.

  • In C++, an lvalue expression yields an object or a function.

  • Roughly speaking, when we use an object as an rvalue, we use the object’s value (its contents).

  • When we use an object as an lvalue, we use the object’s identity (its location in memory).

  • Operators differ as to whether they require lvalue or rvalue operands and as to whether they return lvalues or rvalues.

    • Assignment requires a (nonconst) lvalue as its left-hand operand and yields its left-hand operand as an lvalue.
    • The address-of operator requires an lvalue operand and returns a pointer to its operand as an rvalue.
    • The built-in dereference and subscript operators and the iterator dereference and string and vector subscript operators all yield lvalues.
    • The built-in and iterator increment and decrement operators require lvalue operands and the prefix versions also yield lvalues.
  • Lvalues and rvalues also differ when used with decltype.

    • When we apply decltype to an expression (other than a variable), the result is a reference type if the expression yields an lvalue.
      As an example, assume p is an int*. Because dereference yields an lvalue, decltype(*p) is int&.

    • On the other hand, because the address-of operator yields an rvalue, decltype(&p) is int**, that is, a pointer to a pointer to type int.

4.1.2. Precedence and Associativity

int i = f1() * f2();

We have no way of knowing whether f1 will be called before f2 or vice versa.

int i = 0;
cout << i << " " << ++i << endl; // undefined

The compiler might evaluate ++i before evaluating i, in which case the output will be 1 1.
Or the compiler might evaluate i first, in which case the output will be 0 1.
Or the compiler might do something else entirely.


  • The logical AND (&&) operator guarantees that its left-hand operand is evaluated first.

  • Moreover, we are also guaranteed that the right-hand operand is evaluated only if the left-hand operand is true.

  • The only other operators that guarantee the order in which operands are evaluated are the logical OR (||) operator, the conditional (? 😃 operator, and the comma (,) operator

4.2. Arithmetic Operators

In a division, the new standard requires the quotient to be rounded toward zero (i.e., truncated).

21 % 6; /* result is 3 */ 			21 / 6; /* result is 3 */
21 % 7; /* result is 0 */		 	21 / 7; /* result is 3 */
-21 % -8; /* result is -5 */ 		-21 / -8; /* result is 2 */
21 % -5; /* result is 1 */ 			21 / -5; /* result is -4 */

4.4. Assignment Operators

int i = 0, j = 0, k = 0; // initializations, not assignment
const int ci = i; // initialization, not assignment

1024 = k; // error: literals are rvalues
i + j = k; // error: arithmetic expressions are rvalues
ci = k; // error: ci is a const (nonmodifiable) lvalue

k = 0; // result: type int, value 0
k = 3.14159; // result: type int, value 3
  • The left-hand operand of an assignment operator must be a modifiable lvalue. For example, given

  • The result of an assignment is its left-hand operand, which is an lvalue.

  • The type of the result is the type of the left-hand operand.

  • If the types of the left and right operands differ, the right-hand operand is converted to the type of the left:

  • Under the new standard, we can use a braced initializer list on the right-hand side:

k = {3.14}; // error: narrowing conversion
vector<int> vi; // initially empty
vi = {0,1,2,3,4,5,6,7,8,9}; // vi now has ten elements, values 0 through 9
  • If the left-hand operand is of a built-in type, the initializer list may contain at most one value, and that value must not require a narrowing conversion.

4.5. Increment and Decrement Operators

  • The prefix increments (or decrements) its operand and yields the changed object as its result.

  • The postfix operators increment (or decrement) the operand but yield a copy of the original, unchanged value as its result.

  • The postfix operator must store the original value so that it can return the unincremented value as its result.

// the behavior of the following loop is undefined!
while (beg != s.end() && !isspace(*beg))
	*beg = toupper(*beg++); // error: this assignment is undefined

The problem is that both the left and right-hand operands to = use beg and the right-hand operand changes beg.

The assignment is therefore undefined.

The compiler might evaluate this expression as either

*beg = toupper(*beg); // execution if left-hand side is evaluated first
*(beg + 1) = toupper(*beg); // execution if right-hand side is evaluated first

4.9. The sizeof Operator

C++ sizeof 运算符

  • The sizeof operator returns the size, in bytes, of an expression or a type name.

  • The operator is right associative.

  • The result of sizeof is a constant expression of type size_t.

sizeof (type)
sizeof expr

sizeof an array is the size of the entire array. It is equivalent to taking the sizeof the element type times the number of elements in the array.

sizeof a string or a vector returns only the size of the fixed part of these types; it does not return the size used by the object’s elements.

4.10. Comma Operator

  • The comma operator evaluates from left to right.
  • The comma operator guarantees the order in which its operands are evaluated.
  • The result of a comma expression is the value of its right-hand expression.
  • The result is an lvalue if the right-hand operand is an lvalue.

4.11. Type Conversions

int ival = 3.541 + 3; // the compiler might warn about loss of precision
  1. 3 is converted to double, floating-point addition is done, and the result is a double.

  2. The double result of the addition is converted to int and used to initialize ival.

4.11.1. The Arithmetic Conversions

The rules define a hierarchy of type conversions in which operands to an operator are converted to the widest type.

4.11.2. Other Implicit Conversions

Array to Pointer Conversions

int ia[10]; // array of ten ints
int* ip = ia; // convert ia to a pointer to the first element

This conversion is not performed when an array is used with decltype or as the operand of the address-of (&), sizeof, or typeid operators.

The conversion is also omitted when we initialize a reference to an array.

Pointer Conversions

  • A constant integral value of 0 and the literal nullptr can be converted to any pointer type.

  • A pointer to any nonconst type can be converted to void*.

  • A pointer to any type can be converted to a const void*.

Conversion to const

int i;
const int &j = i; // convert a nonconst to a reference to const int
const int *p = &i; // convert address of a nonconst to the address of a const
int &r = j, *q = p; // error: conversion from const to nonconst not allowed

Conversions Defined by Class Types

string s, t = "a value"; // character string literal converted to type string
while (cin >> s) // while condition converts cin to bool

If the last read succeeded, then the conversion yields true. If the last attempt failed, then the conversion to bool yields false.

4.11.3. Explicit Conversions

Named Casts

cast-name<type>(expression);

Where type is the target type of the conversion, and expression is the value to be cast.

If type is a reference, then the result is an lvalue.

The cast-name may be one of static_cast, dynamic_cast, const_cast, and reinterpret_cast.

static_cast

// cast used to force floating-point division
double slope = static_cast<double>(j) / i;
  • Any well-defined type conversion, other than those involving low-level const, can be requested using a static_cast.

  • A static_cast is often useful when a larger arithmetic type is assigned to a smaller type.

  • A static_cast is also useful to perform a conversion that the compiler will not generate automatically.

void* p = &d; // ok: address of any nonconst object can be stored in a void*
// ok: converts void* back to the original pointer type
double *dp = static_cast<double*>(p);

When we store a pointer in a void* and then use a static_cast to cast the pointer back to its original type, we are guaranteed that the pointer value is preserved.

The result of the cast will be equal to the original address value.

However, we must be certain that the type to which we cast the pointer is the actual type of that pointer; if the types do not match, the result is undefined.

const_cast

A const_cast changes only a low-level const in its operand.

const char *pc;
char *p = const_cast<char*>(pc); 
// ok: but writing through p is undefined ???

Once we have cast away the const of an object, the compiler will no longer prevent us from writing to that object.

If the object was originally not a const, using a cast to obtain write access is legal.

However, using a const_cast in order to write to a const object is undefined. (?)

Only a const_cast may be used to change the constness of an expression.

Trying to change whether an expression is const with any of the other forms of named cast is a compile-time error.

Similarly, we cannot use a const_cast to change the type of an expression:

const char *cp;
// error: static_cast can't cast away const
char *q = static_cast<char*>(cp);
static_cast<string>(cp); // ok: converts string literal to string
const_cast<string>(cp); // error: const_cast only changes constness

reinterpret_cast

reinterpret_cast in C++

A reinterpret_cast generally performs a low-level reinterpretation of the bit pattern of its operands.

int *ip;
char *pc = reinterpret_cast<char*>(ip);

Old-Style Casts

type (expr); // function-style cast notation
(type) expr; // C-language-style cast notation

4.12. Operator Precedence Table

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/103109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中国风?古典系?AI中文绘图创作尝鲜!⛵

&#x1f4a1; 作者&#xff1a;韩信子ShowMeAI &#x1f4d8; 深度学习实战系列&#xff1a;https://www.showmeai.tech/tutorials/42 &#x1f4d8; 本文地址&#xff1a;https://www.showmeai.tech/article-detail/413 &#x1f4e2; 声明&#xff1a;版权所有&#xff0c;转…

Java——B-树

概念 当我们使用avl树或者红黑树进行数据检索时&#xff0c;虽然树是平衡的&#xff0c;可以保证搜索的效率大概是logN。但是当我们的数据量比较大时&#xff0c;只能在内存中存储数据在硬盘中的指针&#xff0c;这时如果我们要检索数据&#xff0c;最少也需要比较树的高度次。…

【算法】单词接龙,合并区间, 二叉搜索树的最近公共祖先,旋转排序数组中的最小值看看有你会的吗?

算法学习有些时候是枯燥的&#xff0c;每天学习一点点 算法题目一. 单词接龙 II 题目描述java 解答参考二. 合并区间 题目描述java 解答参考三. 二叉搜索树的最近公共祖先 题目要求java实现方案四 寻找旋转排序数组中的最小值一. 单词接龙 II 题目描述 按字典 wordList 完成从…

Azure RTOS 嵌入式无线网络框架简化物联网应用开发

一、Azure RTOS概述 Azure RTOS 是一个实时操作系统 (RTOS)&#xff0c;适用于由微控制器 (MCU) 提供支持的物联网 (IoT) 和边缘设备&#xff0c; Azure RTOS 旨在支持高度受限设备&#xff08;电池供电&#xff0c;并且闪存容量不到 64 KB&#xff09;。简而言之&#xff0c;…

某HR分享:2n和n+3的基数不一样,n+3比2n拿得多!仲裁期间不能入职新公司,千万别轻易仲裁,得不偿失!...

被裁员时&#xff0c;要2n还是要n3&#xff1f;是否选择仲裁&#xff1f;一位hr说&#xff0c;跟走过仲裁的同学和律师朋友打听了下&#xff0c;原来2n和n3完全不一样。n3的n取的是“非私营单位从业人员平均工资”的三倍&#xff0c;杭州市是3.2万。2n的n取的是“全社会就业人员…

Android设计模式详解之单例模式

前言 定义&#xff1a;确保某一个类只有一个实例&#xff0c;而且自行实例化并向整个系统提供这个实例。 使用场景&#xff1a;确保某个类有且仅有一个对象的场景&#xff0c;避免产生多个对象消耗过多的资源。比如要访问IO和数据库资源&#xff0c;应该考虑使用单例模式。 …

JAVA开发(数据库表设计)

对于大型系统数据库设计&#xff0c;需要进行一定的规划和规范&#xff0c;才能方便系统扩展和维护。一般系统的数据库设计要求&#xff0c;有数据库表系统规划&#xff0c;数据库表系统命名规范和设计规范。 一、数据库表系统规划 1、按系统规划或者按微服务规划 2、按业务…

Matlab论文插图绘制模板第71期—三维饼图(Pie3)

在之前的文章中&#xff0c;分享了Matlab饼图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一下三维饼图的绘制模板。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;Matlab论文插图绘制模板系列&#xff0c;旨在降低大家使用Matlab进行科研绘图的门槛&#xff0…

最大子段和(动态规划详细解析)

最大子段和 题目描述 给出一个长度为 nnn 的序列 aaa&#xff0c;选出其中连续且非空的一段使得这段和最大。 输入格式 第一行是一个整数&#xff0c;表示序列的长度 nnn。 第二行有 nnn 个整数&#xff0c;第 iii 个整数表示序列的第 iii 个数字 aia_iai​。 输出格式 …

读取excel文件read_excel()--Pandas

1. 函数功能 读取excel文件&#xff0c;支持读取xls,xlsx,xlsm等类型的EXCEL文件。能够读取一个sheet表或多个sheet表 2. 函数语法 pandas.read_excel(io, sheet_name0, *, header0, namesNone, index_colNone, usecolsNone, squeezeNone, dtypeNone, engineNone, converte…

MCMC算法

一. MCMC算法定义 MCMC是Markov chain Monte Carlo的缩写&#xff0c;即马尔可夫链蒙特卡罗方法。MCMC是一组利用马尔可夫链从随机分布中取样的算法。生成的马氏链即是对于目标分布的近似估计。常见算法&#xff1a; Metropolis-Hastings算法Gibbs取样算法Hamiltonian Monte C…

单片机AT89C51数码管数字时钟和闹钟二

详细代码讨论加我QQ&#xff1a;1271370903 一、课题的方案设计与论证 1.1摘要 近年来随着计算机在社会领域的渗透和大规模集成电路的发展&#xff0c;单片机的应用正在不断地走向深入&#xff0c;由于它具有功能强&#xff0c;体积小&#xff0c;功耗低&#xff0c;价格便宜…

【我的渲染技术进阶之旅】你可能永远猜不到为什么Filament项目命名为TNT?

文章目录一、疑惑为啥叫TNT&#xff1f;二、寻找真相2.1 百度TNT关键字2.2 GitHub issue2.3 GitHub Discussion三、总结一、疑惑为啥叫TNT&#xff1f; 在我之前的博客【我的渲染技术进阶之旅】如何编译Filament的windows版本程序&#xff1f; 有介绍如何编译Windows版本的Fil…

React 18:Ref(获取DOM对象)

ref介绍 React中所有的操作默认都是在React元素上进行&#xff0c;然后再通过虚拟DOM应用到真实页面上的。这样做的好处我们不在赘述。 虽然如此&#xff0c;在React中依然为我们提供了可以直接访问原生DOM对象的方式。ref就是干这个事的。 ref是reference的简写&#xff0c…

【排序】详细聊聊归并排序(含非递归)

目录 归并排序的基本思想&#xff1a; 递归算法&#xff1a; 递归算法的思路分析&#xff1a; 开辟数组的函数&#xff1a; 递归的函数&#xff1a; 非递归算法&#xff1a; 非递归的思路分析&#xff1a; 边界问题&#xff1a; 时间复杂度和空间复杂度分析&#xff1a…

重建农场2.0:实景三维数据中心一站式解决方案

面向实景三维中国建设&#xff0c;如何扩大产能&#xff0c;不断提升实景三维数据中心的重建算力水平&#xff1f;如何满足快速迭代的需求&#xff0c;不断提升数据中心的应变能力&#xff1f;如何做到“一机多能”&#xff0c;不断外延数据中心的硬件价值&#xff1f;在前不久…

jquery获取父/子iframe页面的URL

最近因为要演示,做个临时ifame框架页面,因此子页面要根据父页面url来指定跳转。下面为ifame页面: 1、获取子页面url: var currentpath = window.location.pathname; console.log(currentpath); 输出为:/JG/TJ_JILU.aspx 2、获取父页面url: let currentTopHref = wind…

IDEA 注释模版

类的主注释 /*** description TODO* author Gaoxueyong* date ${DATE} ${TIME}* version 1.0*/方法的注释 1、创建自己的分组 选择右侧Template Group并输入名称 2、创建自己的模版 选择自己创建的分组然后选择Live Template 然后在Template text框内写入 *** $description…

脑图谱的一致性问题

脑图谱的意义及一致性问题 我们如何定义大脑的解剖结构&#xff0c;并将这些结构与大脑的功能联系起来&#xff0c;可以限制或增强我们对行为和神经系统疾病的理解大量可用的脑图谱给研究健康群体和患病人群的可重复性和描述大脑不同区域参与各种疾病的荟萃分析带来了问题——…

全力推进企业数智赋能发展主线,低代码任重道远

信息化进程 纵观近半个世纪以来我国信息化的发展&#xff0c;经历了20世纪80年代以个人计算机普及应用为特征的数字化阶段&#xff08;信息化1.0&#xff09;&#xff1b;20世纪90年代中期以互联网大规模商用为特征的网络化阶段&#xff08;信息化2.0&#xff09;&#xff1b;…