当前位置: 首页 > news >正文

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.lryc.cn/news/140419.html

相关文章:

  • 利用lammps模拟蓝宝石在水润滑环境下的抛光
  • 3.BGP状态机和路由注入方式
  • 微信开发之一键创建微信群聊的技术实现
  • 设计模式二十:观察者模式(Observer Pattern)
  • Linux操作系统--CentOS使用初体验
  • 搭建HAProxy + Keepalived高可用
  • 使用Python爬虫定制化开发自己需要的数据集
  • java八股文面试[java基础]——接口和抽象类的区别
  • head 请求了解过吗?如何用 get 模拟 head 请求?不需要服务器返回数据,怎么实现?
  • Redis笔记——(狂神说)待续
  • 基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v7.0版已发布
  • BLFS学习系列 第26章. 显示管理器 —— 总述
  • macOS上编译obs-studio
  • Oracle数据库快速入门
  • Linux内核学习(十)—— 块 I/O 层(基于Linux 2.6内核)
  • SpringMVC 写个 HelloWorld
  • ARM--day7(cortex_M4核LED实验流程、异常源、异常处理模式、异常向量表、异常处理流程、软中断编程、cortex_A7核中断实验)
  • Java中LinkList的基本介绍和细节讨论。双向链表的代码和LinkList的源码。LinkList和ArrayList的比较与选择。
  • Proteus软件安装包分享(附安装教程)
  • “图为科技——什么是边缘计算“
  • SpringCloud教程 | 第六篇: 分布式配置中心(Spring Cloud Config)
  • mysql 错误码
  • HTML的form表单标签详解~
  • Kafka 消费者“group_name”组正在永远重新平衡
  • 高并发编程-3. Amdahl(阿姆达尔)定律与Gustafson定律
  • ffmpeg之常用的命令行参数
  • tomcat服务器
  • 【面试题】MVC、MVP与MVVM模式是什么?
  • 网络安全02-C段扫描、开放端口
  • vscode流程图插件使用