C++避坑——most vexing parse问题

1."坑"的问题是什么?

先看一段代码:

class Functor
{
public:void operator()(){std::cout << "我是线程的初始函数" << std::endl;}
};int main()
{std::thread t(Functor());// 强制高速编译器这是一个构造函数!t.join();return 0;
}

按照正常的思路分析这段代码应该是这样的:

Functor类当中有一个"operator()"成员函数,这就注定Functor类对象是一个可调用对象(当成函数一样使用)。那么在"std::thread t(Functor())"当中,t的构造函数的参数是一个Functor类的匿名对象,也就相当于传递了一个线程的初始函数。这句代码之后,输出结果应该为"我是线程的初始函数"才对。

但是这段代码的结果却是:

啥玩意???竟然报错!!??后面反复编译了几次,依然是这个结果。这就让我陷入了沉思...... 

实际上"std::thread t(Functor())"被编译器解释成了一个函数声明。即,一个函数名为t,返回类型为std::thread,参数为函数指针(指向一个无参的,返回类型为Functor的函数)。

2.从另一个角度去看"坑"

先看这么一段代码:

int main()
{std::vector<int> vec(std::string());return 0;
}

放心,不报错,并且编译过。

它也被解释成了函数声明。问题就在于,它为什么被解释成一个函数声明?

如果我把它写成这样:

int main()
{//std::vector<int> vec(std::string());std::vector<int> func(std::string p());return 0;
}

是不是就清楚多了?如果还不清楚,我再这样写一段代码:

int main()
{//std::vector<int> vec(std::string());std::vector<int> func(std::string p());return 0;
}
std::string p()
{return "";
}

清楚了吧!func后面的括号写的是一个函数。也就说,"std::vector<int> func(std::string p());"是一个函数声明,返回值为std::vector<int>,参数类型为一个函数指针(指向一个返回类型为std::string、无参的函数)。

再回看"std::vector<int> vec(std::string());"这句话,需要注意一个细节,那就是函数声明的形参类型可以不用给名字。这就透了吧!

还有一个问题,"std::vector<int> vec(std::string());"当中的"(std::string())"明明是一个函数,我为什么要说它是一个函数指针?这里又涉及到一个细节,在C/C++中,没有函数类型,这里的"(std::string())"会自动被解析成指针!

如果还不理解,看这么一段代码:

void test(int arr[]);

test函数接收的形参真的是一个数组吗?当然不是咯,这里的arr是一个指针!

3.解决方法

所以在C++11当中又补充了一个"初始化列表",像下面这么用:

class Functor
{
public:void operator()(){std::cout << "我是线程的初始函数" << std::endl;}
};int main()
{std::thread t{Functor()};// 强制告诉编译器这是一个构造函数!t.join();return 0;
}

所以最终的输出结果就是正确的咯!

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端进阶之———浏览器调试巧技

有幸的参加了一次腾讯的面试&#xff0c;被面试官问到了JS能不能在浏览器上import依赖已经遇到一个错误函数应该怎么解决。之前的经验是做一些简单的html&#xff0c;css样式调试以及他的报错信息&#xff0c;忽略了浏览器js调试的强大功能。觉得还是非常有必要的&#xff0c;很…

锁的相关策略

乐观锁vs悲观锁 指的不是具体的锁,是一个抽象的概念,描述的是锁的特性,描述的是一类锁 乐观锁 假设数据一般情况下不会产生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并发冲突进行检测,如果发现并发冲突了,就让返回用户错误的信息,让用户决定如何去做.(…

从爬楼梯到斐波那契数列:解密数学之美

题目描述 我们来看看力扣的一道经典问题70. 爬楼梯 递归 假设n级台阶有climbStairs(n)种方法爬到楼梯顶。如果有n级台阶&#xff0c;如果第一次往上爬1级台阶&#xff0c;就会剩下n-1级台阶&#xff0c;这n-1级台阶就有climbStairs(n-1)种方法爬到楼梯顶&#xff1b;如果第一…

es的索引管理

概念 &#xff08;1&#xff09;集群&#xff08;Cluster&#xff09;&#xff1a; ES可以作为一个独立的单个搜索服务器。不过&#xff0c;为了处理大型数据集&#xff0c;实现容错和高可用性&#xff0c;ES可以运行在许多互相合作的服务器上。这些服务器的集合称为集群。 &…

uniapp使用uni.chooseLocation()打开地图选择位置

使用uni.chooseLocation()打开地址选择位置&#xff1a; 在Uniapp源码视图进行设置 添加这个属性&#xff1a;"requiredPrivateInfos":["chooseLocation"] ​ </template><view class"location_box"><view class"locatio…

企业博客搭建:经营好企业博客,能让你的业务蹭蹭上涨!

企业博客本身作为企业产品知识的沉淀&#xff0c;搭建并且经营好企业博客不仅有利于企业文化建设&#xff0c;更可以利用博客来推动业务增长。 何谓企业博客营销&#xff1f;简单地说&#xff0c;就是利用HelpLook这种工具创建并开展网络营销活动&#xff0c;称之为博客营销。 …

CH02_重构的原则(什么是重构、为什么重构、何时重构)

什么是重构 重构&#xff08;名词&#xff09;&#xff1a;对软件内部结构的一种调整&#xff0c;目的是在不改变软件可观察行为的前提下&#xff0c;提高其可理解性&#xff0c;降低其修改成本。 重构&#xff08;动词&#xff09;&#xff1a;使用一系列重构手法&#xff0…

云原生之使用Docker部署SSCMS内容管理系统

云原生之使用Docker部署SSCMS内容管理系统 一、SSCMS介绍二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载SSCMS镜像五、部署SSCMS内容管理系统5.1 创建SSCMS容器5.2 检查SSC…

SpeedBI数据可视化工具:丰富图表,提高报表易读性

数据可视化工具一大作用就是能把复杂数据可视化、直观化&#xff0c;更容易看懂&#xff0c;也就更容易实现以数据驱动业务管理升级&#xff0c;因此一般的数据可视化工具都会提供大量图形化的数据可视化图表&#xff0c;以提高报表的易懂性&#xff0c;更好地服务企业运营决策…

【React基础全篇】

文章目录 一、关于 React二、脚手架2.1 create-react-app 脚手架的使用2.2 项目目录解析2.3 抽离配置文件2.4 webpack 二次封装2.4.1 集成 css 预处理器2.4.2 配置解析别名 2.5 setupProxy 代理 三、JSX3.1 jsx 语法详解3.2 React.createElement 四、组件定义4.1 类组件4.2 函数…

python print ljust 文本对齐打印 对齐打印名册

背景 在python部分场景下&#xff0c;我们需要打印输出一些文本消息&#xff0c;但我们又无法预测可能的打印内容是什么。这种情况下&#xff0c;我们要对齐打印这些文本&#xff0c;是比较比较难以处理的。 例如下面是一列姓名&#xff0c;和对应的一列手机/电话号&#xff0…

2023企业网盘产品排行榜揭晓:选择最适合你的企业网盘工具

企业网盘产品已成为企业文件管理协作的主要选择之一&#xff0c;无论是在文件管理方面&#xff0c;还是团队协作上&#xff0c;企业网盘都表现优秀。为了帮助企业选到心怡的企业网盘产品&#xff0c;我们综合了不同的产品测评网站意见&#xff0c;整理了2023企业网盘产品排行榜…