意想不到的结果:Foo(m)可能是在定义名为m的对象

news2024/9/20 10:51:09

文章目录

  • 例一:`Foo(m);` 是定义名为 `m` 的对象
  • 例二:`Foo(m).i;` 传入实参 `m`
  • 例三:`func(Foo(m));` 传入实参 `m`
  • 例四:`S(cout)(1)` 定义名为 `cout` 的对象
  • 例五:`S(std::cout)(1)` 传入实参 `std::cout`

你知道吗,如果 Foo 是一个类,那么执行含有 Foo(m) 的语句时,可能并不会把 m 作为实参传给 Foo 的构造函数!还有一种可能是调用默认构造函数,去定义一个 Foo 的对象 m

那这两种情况分别在什么时候发生呢?我们知道,C++中圆括号 () 有时候是多余的存在,比如 int i = (1+3);,把括号去了 int i = 1+3;,两条语句是等价的。对于含 Foo(m) 的语句,这对括号也可能是多余的。C++处理这种语句的原则是能简单就简单,如果能省略括号(无语法错误)那就省略!当然了,省略完括号得加上一个空格,变成 Foo m。下面举五个例子。首先我们定义一个 Foo 类。

struct Foo
{
    int i;
    Foo(int i0) : i(i0) {}
};

例一:Foo(m); 是定义名为 m 的对象

对于 Foo(m); 括号省略后,语句变成 Foo m;。语法没有任何问题,所以编译器决定把括号省略。

int main()
{
    Foo(m);
    return 0;
}

但是上述代码会在编译时产生错误,因为 Foo 没有默认构造函数啊,所以 Foo m; 当然是会报错的。

例二:Foo(m).i; 传入实参 m

对于Foo(m).i;,我们把括号去掉,语句变成 Foo m.i;,显然语法错误。编译时会报 m 未定义的错误。

这就说明括号是不能去的,即 m 会作为实参传给 Foo 的构造函数,创建一个匿名对象,然后访问其名为 i 的数据成员。

// main函数中
int m = 10;
cout << "Output:\t" << Foo(m).i << '\n';

Output: 10

例三:func(Foo(m)); 传入实参 m

func 是一个函数,有一个 Foo 类型的形参。我们把括号去掉,语句变成 func(Foo m); ,显然是非法的,因为实参里面不能有类型名。故括号不能去,即 m 应作为参数传给 Foo 的构造函数。

int func(Foo foo) { return foo.i; }

int main()
{
    int m = 10;
    cout << "Output:\t" << func(Foo(m)) << '\n';
    return 0;
}

Output: 10

为了说明下面两个例子,我们定义一个新的类 SS 重载了调用运算符 (),因此其对象是一个函数对象。

#include <iostream>
using std::cout;
using std::cerr;

struct S
{
    ostream &os;
    S(ostream &o = cerr) : os(o) {}
    void operator()(int x)
    {
        os << "x = " << x << '\n';
    }
};

例四:S(cout)(1) 定义名为 cout 的对象

cout
我们先来试试看 S()(1); 会有什么结果。它调用默认构造函数,创建一个可调用的函数对象,os 初始化为 cerr。这个对象接受一个实参 1 然后被调用,由 cerr 输出 x = 1

如果我不想默认初始化,便传入 coutS 的构造函数作为实参。此时语句变为 S(cout)(1)。这能不能达到预期效果呢?我们试着把括号去掉,变成 S cout(1),这看着确实是语法正确的,意思是通过传入实参 1 ,来定义一个名为 coutS 对象。既然语法合法,则括号可去。

// main函数
S(cout)(1);

但编译显然是会报错的,为什么呢,因为 S 并没有接受一个 int 对象的构造函数。

这倒还算好的,因为报错了,我们能通过错误检查出我们代码的问题。如果 S 果真有接受一个 int 对象的构造函数,便不会报错,但达不到我们的预期效果,代码问题的排查也就更困难了。

那如果要达到预期效果,正确的做法是什么呢?请看例五。

例五:S(std::cout)(1) 传入实参 std::cout

加上了全局作用域,这括号可就去不得了:S std::cout(1) 显然非法,std::cout 不能作为我们自定义对象的名字。因此 std::cout 会如预期一样作为实参传入 S 的构造函数。

S(std::cout)(1);

x = 1

这就是为什么很多人建议用 std::cout 而非 cout 的原因,就是怕上述的情况。using std::cout; 倒还好了,只要我们不主动定义 名字叫 cout 的对象一般不会出错,除非是上述这种编译器去括号来定义的这种意想不到的错误。相较而言,using namespace std; 是风险最高的,你不知道啥时候,自己自定义的一个对象名字就把标准库的给隐藏了。

但是图省事,对于使用次数较多的名字,我还是会用 using std::cout;;对于只用一两次的名字,我就不用 using 声明了吧,而是加上 std::。另外自己要清楚 Foo(m) 的这些情况,如此写出与预期效果相符的代码也就容易多了。

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

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

相关文章

vue3 watch 监听响应式数据变化

主要是用来监听ref 或者reactive 所包裹的数据才可以被监听到 <template><input type"text" v-model"message"> </template> <script setup lang"ts">import {ref, watch} from "vue";let message ref<s…

powerdesigner画UML组件图初步

组件图 组件图是用来描述组件与组件之间关系的一种UML图&#xff0c;组件图在宏观层面上显示了构成系统某一特定方面的实现结构。 组件图可以用来显示组件之间的依赖关系&#xff0c;以及组件的接口和调用关系。 组件图由组件&#xff0c;接口&#xff0c;组件图中的关系&…

20230124英语学习

Why Do We Still Procrastinate Despite It Causing So Much Stress? 明知道拖延不好&#xff0c;为何还会拖延&#xff1f; Are you procrastinating?I am.I have been delaying writing this article for the last few days even though I knew I had a deadline. I have …

从零到一:复现 DIR-815 栈溢出漏洞

从零到一&#xff1a;复现 DIR-815 栈溢出漏洞 实验环境 执行命令uname -a可以查看到当前系统版本 我这边采用桥接模式进行实验。 环境搭建 文章命令操作均在root下操作&#xff0c;且git clone xxxx.git下载所用到工具都均下载保存到/opt/tools/文件夹下&#xff0c;方便统…

OKC和802.11R的知识小科普

欢迎来到东用知识小课堂&#xff01;1.什么是漫游简单来说&#xff0c;就是设备从一个AP&#xff0c;连接到另一个AP。IP地址不需要重新申请。整个过程需要尽可能快的进行&#xff0c;否则对于用户而言&#xff0c;就会发现网络出现卡顿。而为了安全&#xff0c;网络的认证过程…

【Python】使用pyinstaller打包py程序为exe应用程序时,出现“Tcl报错闪退”的解决办法

问题概述 使用pyinstaller -F的命令进行py程序转为exe程序时&#xff0c;打包后的exe程序会出现闪退报错的情况&#xff1a; 解决办法 1. 检查“环境变量”tcl和tk是否配置好&#xff1a; 查看系统高级设置>>>环境变量>>>系统变量 博主使用anaconda进行p…

河道污染物识别系统 python

河道污染物识别系统通过pythonyolo深度学习技术&#xff0c;对现场画面中河道污染物以及漂浮物进行全天候实时监测&#xff0c;当监测到出现污染物漂浮物时&#xff0c;立即抓拍存档触发告警。与C / C等语言相比&#xff0c;Python速度较慢。也就是说&#xff0c;Python可以使用…

计算机组成原理 | 第一章:概论

文章目录&#x1f4da;冯诺依曼计算机的特点&#x1f4da;计算机硬件组成框图&#x1f4da;计算机硬件的主要技术指标&#x1f407;非时间指标&#x1f407;时间指标&#x1f511;计算技巧归纳&#x1f4da;小结&#x1f511;本章掌握要点&#x1f407;补充思考题&#x1f4da;…

Froala Editor内容中删除内联样式

Froala Editor内容中删除内联样式 易于集成-编辑器可以在任何时间内集成到任何类型的项目中。它只需要基本的JavaScript和HTML编码知识。 流行-HTML编辑器在开发人员中很流行&#xff0c;它有最流行的开发框架的插件。 易于升级-将所有自定义内容与编辑器文件夹分开&#xff0c…

3.1存储系统基本概念

文章目录一、引子二、存储器的层次化结构1.层次化结构&#xff08;1&#xff09;金字塔&#xff08;2&#xff09;案例&#xff08;3&#xff09;Cache&#xff08;4&#xff09;寄存器&#xff08;5&#xff09;辅存和外存2.速度与价格举例&#xff08;1&#xff09;主存和Cac…

智障税品牌种草收割流

1.量化量化这一块我后续应该不更新了&#xff0c;因为目前我接触的都是赚钱层次的了发出去都是砸自己的饭碗目前我在8个交易所都是市商费率有需要费率的可以合作我在跑的策略为&#xff1a;套利、高频、预测《赚麻》当你有了顶级费率和速度&#xff0c;什么策略都可以赚钱2.引流…

88.【员工管理系统-springBoot】

SpringBoot(十三)、员工管理系统SpringBoot1.准备工作(1).导入我们所需要的环境依赖(2).首页的Controller与View (静态资源Thymeleaf接管)2.国际化(1).设置字符编码为UTF-8(2).添加文件资源目录 i18n(3).注册国际化实现(4).国际化的实现 index.html(5).英文与汉文的交互(6).在s…

[QMT]08-从本地行情数据解析历史K线信息

用python解析QMT本地数据获取本地行情数据get_local_data(field_list[], stock_code[], period1d, start_time, end_time, count-1,dividend_typenone, fill_dataTrue, data_dirdata_dir)释义从本地数据文件获取行情数据&#xff0c;用于快速批量获取历史部分的行情数据参数fie…

谈谈线程安全问题及其解决方法

本文讲述一下线程的安全问题及解决方法。 一 线程安全问题举例说明 在电影院售票的场景&#xff0c;假使有100张票待售&#xff0c;有3个窗口在售票&#xff0c;如图所示&#xff1a; 三个窗口都卖出票1&#xff0c;一个票被卖了3次&#xff0c;多线程访问共享数据“票”&am…

【代码阅读】MSC-VO

MSC-VO是ICRA2022的一篇点线视觉SLAM论文&#xff0c;本身是在ORBSLAM2的基础上改进的&#xff0c;改进的部分在于为SLAM系统引入了线段&#xff0c;并且使用了曼哈顿坐标系与结构化约束进行优化&#xff0c;之前看过的论文记录可以参考链接&#xff0c;年前把线段匹配和均匀化…

CMake的介绍

1.示例代码其实都非常简单&#xff0c;直接使用 GCC 编译器编译即可&#xff0c;连 Makefile 都不需要。在实际的项目中&#xff0c; 一个工程中可能包含几十、成百甚至上千个源文件&#xff0c; 这些源文件按照其类型、功能、模块分别放置在不同的目录中&#xff1b;面对这样的…

Kafka-生产者分区

一、分区的好处 便于合理使用存储资源&#xff0c;每个Partition在一个Broker上存储&#xff0c;可以把海量的数据按照分区切割成一块一块数据存储在多台Broker上。合理控制分区的任务&#xff0c;可以实现负载均衡的效果。提高并行度&#xff0c;生产者可以以分区为单位发送数…

Git自学日记

添加暂存区 git add 提交本地库 git commit -m “日志信息” 修改文件 vim 修改文件名 按i进入编辑模式 按esc退出编辑摸模式 :wq 保存更改 历史版本 git reflog 查看版本信息 git log 查看版本详细信息 版本穿梭 git reset --hard 版本号 分支操作 创建分支: git br…

【数据结构】7.1 查找的基本概念

文章目录1. 查找表2. 关键字3. 查找4. 动态查找表和静态查找表5. 平均查找长度1. 查找表 问题&#xff1a;在哪里找&#xff1f; 答&#xff1a;在一个新的数据结构查找表上面找。 查找表&#xff1a; 查找表是由同一类型的数据元素&#xff08;或记录&#xff09;构成的集合…

操作系统真相还原_第5章第3节:加载内核(ELF格式分析)

文章目录用C语言写内核(例)二进制程序的运行方法ELF格式的二进制文件ELF文件格式数据类型ELF header的结构Elf32_Phdr的结构ELF文件实例分析将内核载入内存当前的OS信息当前内存规划源码boot.incmbr.sloader.s内核编译并写入硬盘用C语言写内核(例) 源码&#xff1a; int func…