首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

令人沮丧C++性能调试

之后,我们将比较三种主要编译GCCClang 和 MSVC)在这方面的表现,并讨论一些潜在改进或解决方案。...不提倡使用 std::vector,而提倡使用 T*,或者至少通过指针进行迭代(即通过 std::vector::data),不是通过迭代。...MSVC 没有与 -Og 相对应东西,大多数游戏开发者使用 MSVC 作为他们主要编译! 即使 -Og 无处不在,但它仍然不及 -O0——对于高效调试会话来说,它可能仍然内联太多代码。...我们可以说函数模板不是为强制转换和位操作创建轻量级抽象正确模型,类模板和轻量级类型,如 std::vector::iterator,也是如此。...最后,不要忘了,直接解决这个问题,不是绕过它,我们还可以从中获得其他好处,比如更快编译

94820

Qt高级编码约定

谨慎明智地使用模板,不仅仅是因为可以使用。提示:使用编译自动测试可以查看测试中所有编译是否支持C++功能。...即使为共享库定义初始化程序执行时间,在插件中移动该代码或静态编译也会遇到麻烦: /* 全局作用域 */ static const QString x; /* 错误: 需要运行默认构造函数初始化...*/ static QString *ptr = 0; /* 指向对象指针是ok, 不需要运行代码来初始化ptr。...避免操作 不要继承模板/工具类 由于析构函数不是virtual,这会导致潜在内存泄漏问题。 这些符号没有被导出(大部分是内联),会导致报符号冲突编译错误提示。...因为是GCC 4.7和更早版本存在一个错误,需要捕获此错误,但如果您这样做,则Clang 5.0和更高版本将产生警告: void Foo::something() { ...

1.7K30
您找到你想要的搜索结果了吗?
是的
没有找到

C语言边角料:结构体中指针类型成员变量,它类型重要吗?

一、前言 二、问题描述 三、把类型改为 void 指针类型 四、总结 一、前言 昨天在编译代码时候,之前一直OK一个地方,却突然出现好几个 Warning!...我们用其他编译试一下: (1) clang $ clang main.c -m32 -o main -I./ main.c:18:20: warning: incompatible pointer...三、把类型改为 void 指针类型 把 struct _Data2_ 中 next 成员,改为 指向 void 型指针,然后在 main 函数中操作它。...这又回到了指针本质: 指针就是一个地址,至于如何来解释这个地址中内容,这是由定义这个指针所指定数据类型来决定 结合代码来看:虽然d2.next是一个 void 型指针,但是它的确存储一个 地址...不过,从中我们也看到了一个现象:gcc编译在面对结构体,主要关心是结构体在内存空间中所占用空间大小,对其内部指向结构体类型指针,并没有严格检查是否存在,g++ 在这一点就做严谨一些

51240

第6章 函数

这样的话,如果在头文件中实现某个函数函数又被多个源文件使用,那么在编译正常,而在链接就会报错,某些函数多次重复定义。...// 错误,实参不是含有 10个整数数组 print(j); // 错误,实参不是含有 10个整数数组 使用 main函数处理命令行选项,通常会写成下列两种形式...在上面两个表达式中,argv是一个数组,它元素是指向 C风格字符串指针 argv又可以看成是指向首元素指针,因此 argv就是一个二级指针,所以也就有第二个表达式写法。...10.initializer_list提供对一系列相同类型元素轻量级存储和访问能力,值初始化列表元素永远是常量值。在拷贝或赋值,执行也是“类指针拷贝”,原始列表和副本共享元素。...基于这个原因,内联函数和 constexpr函数通常定义在头文件中。也因为它们可以多次定义,所以即使定义在头文件中,链接也不会出现多次定义错误普通函数这样做就会出错。

1.2K70

查看自动类型推导结果方法

++代码转换成最终形式C++代码,有点类似于C/C++预处理一样,把一些宏代码替换成真实代码一样,但它功能更进一步也更强大,该工具支持基于范围循环、结构化绑定、生成默认构造函数初始化列表、...编译打印编译肯定是知道变量类型,但是它没法直接告诉你,有一个可以让编译告诉你办法,就是编译发生错误编译在报告错误信息中肯定会提到导致此错误类型,因此我们可以声明一个如下模板:template...所以我们想要查看哪个变量类型,只要将这个变量类型作为模板形参去实例化它,就会导致一个错误,在编译给出错误信息里就会显示出这个变量具体类型,如下所示:const int x1 = 1;auto...这时可以采用另外一种手段来输出变量类型,跟上小节中例子一样借助模板技术,实现一个模板函数,在模板函数中利用编译提供宏,把这个函数原型打印出来,函数原型中就包含函数参数个数及其类型,这个宏由于不是...C++标准中定义,是由各编译扩展,因此名称不一样,在GCC/Clang中是__PRETTY_FUNCTION__,在微软MSVC中是__FUNCSIG__,如下代码:#include <iostream

7410

如何在编码阶段减少代码中bug?

静态分析工具能够在代码未运行情况下分析源代码,发现代码中bug。在C/C++程序中,静态分析工具可以发现程序错误,如空指针取消引用、内存泄漏、被零除、整数溢出、越界访问、初始化前使用等。...我第一次也错误认为这段代码会打印“ON”。 如果我们用Clang编译,又有什么结果呢?...Clang是一个优秀静态分析,能够分析代码中潜在问题。对于上面的问题,GCC编译加上-Wall 和-Wpedantic编译选项也可以分析出bug。...和GCC主要任务是编译代码,静态分析也并不是在每次编译都需要,而且编译在做静态分析需要花费大量时间。...比如空指针,除零,整数溢出,无效移位操作,无效转换,STL无效用法,内存管理,空指针引用,越界检查,未初始化变量,未使用或者重复代码等。

1.3K30

编译玄学研究报告】第五期——三十年老娘倒绷孩儿

考虑到凡事不可把话说太绝,我顿了顿补充道:“是不是你忘记打开-fms-extensions?这是常见错误。” “加了,因为这的确是你代码出现编译故障常见原因,所以我第一间就处理了……呐!...实践中经常会发现,clanggcc语法要严格,gcc很多时候在语法风格上更加“放飞自我”,因此clang中可以通过编译代码,怎么会在GCC中无法编译通过呢? “Bug!一定是编译Bug!”...,clang是正常认可0x12345678作为逗号表达式返回值; clang并没有认为这个表达式不是常量; clang也没有认为这个静态常量 s_wTest 初始化有什么不妥; 如果觉得这个warning...翻译一下就是: 常量表达式不应包含赋值、递增、递减、函数调用或逗号运算符…… 问题似乎是水落石出了:这的确是一个由C99明确规定“feature”而非编译"Bug"。...clang和IAR显然因为某种原因(我猜是为了方便)在编译C代码(而非C++代码)也同时移除了这一限制——这在某种程度上误导我们得出了“好学生GCC有Bug”错误结论。

54330

Auto-Vectorization in LLVM

有些程序员使用'restrict'关键字来通知编译指针是分离,但是在我们示例中,循环向量器无法知道指针A和B是唯一。...这个循环使用C++迭代,这些指针指针不是整数索引。循环矢量器检测指针感应变量,并对该循环进行矢量化。这个特性很重要,因为许多C++程序使用迭代。...还可以在对结构成员指针访问上添加运行时检查。 支持许多变体,但是有些依赖于未定义行为被忽略变体(就像其他编译一样),仍然没有被矢量化。...有关这些函数列表,请参见下表。 ? 请注意,如果库调用访问外部状态(如“errno”),优化可能无法将与这些内部函数对应数学库函数矢量化。...当向量化和展开因子较大,行程计数较小循环可能会将大部分时间花费在标量(不是矢量)代码中。

3.1K30

c++17好用新特性总结

inline变量出现后,我们可以直接将全局变量定义在头文件中,不用担心出现redefine错误信息。...有兴趣朋友可以看看下面两篇文章: 《c++ inline variable 内联变量 c++17》 《GCCClang 在C模式,较低优化等级下,链接对内联函数报未定义错误,为什么?》...,结构化绑定结果并不是变量,c++标准称之为名字/别名,这也导致它们不允许被lambda捕获,但是gcc并没有遵循c++标准,所以以下代码在gcc可以编译clang编译不过。...常用于可能失败函数返回值中,比如工厂函数。在C++17之前,往往使用T*作为返回值,如果为nullptr则代表函数失败,否则T*指向真正返回值。...需要注意是,c++17只提供一个库级别的variant实现,没有对应模式匹配(Pattern Matching)机制,最接近std::visit又缺少编译优化支持,所以在c++17中std

2.9K10

1.Win10+VsCodeCCPP编译环境搭建

印象最深是关于函数返回局部指针变量处理: eg: char * fun() { char *p = "hello"; return p; } 这个函数输入到VS里面是完全没有警告和错误...但是实际上CPP是不建议把字符串常量赋值给非常量字符指针(C语言中不会报错)。同样代码在VScode选择clang编译就会出现警告。...还有:return p;这个是有内存风险,局部指针创建对象在栈上,返回p时候函数调用完毕,指针被赋值给其他全局变量的话,栈上空间就会被释放掉,所以这个也是有警告。...重启之后,Win+r输入cmd打开命令行,分别输入gccclang后回车。 ? 出现如上所示提示认为安装成功。 法2....但貌似clang默认开启gcc不接受此参数 "--target=x86_64-w64-mingw", // clang默认target为msvc,不加这一条就会找不到头文件

4.6K70

const 使用总结

当程序员看到使用const修饰代码就知道不应该修改对应对象值,编译则会强制实施这个约束,任何违反这个规定代码会在编译期间报错。...对于内置类型,还是建议使用传值方式,因为引用在底层一般是使用指针来实现,对于内置类型反而更浪费资源,而且编译也可以做优化。对于自定义类型,一般情况下建议定义成const引用,不是普通引用。...const,即在成员函数参数列表之后加上const关键字,表示this是一个指向常量指针,我们也这个成员函数为常量成员函数。...常量对象只能调用常量成员函数,也就是说不允许通过常量成员函数修改对象内部数据或者状态,但有可能出现这种情况,常量成员函数虽然符合要求,因此欺骗过编译通过编译。...,编译利用实参来推断出模板实参,根据模板实参来生成一个函数实例。

8010

GCC -O2 踩坑指南:严格别名(Strict Aliasing)与整数环绕(Integer Wrap-around)

1、什么是别名(alias) 在 C 和 C++ 中,当多个左值 lvalue 指向同一个内存区域,就会出现别名(alias)。...类型双关经常应用在编译、序列化、网络传输等领域。 类型双关一般做法是通过别名(alias)来实现,通过获取对象地址,将其转换为我们想要重新解释类型指针,然后访问该值。...int a;float *ptr = (float *)&a;printf("%f\n", *ptr); 2、什么是严格别名 严格别名就是编译当看到多个别名(alias),会在一定规则下默认它们指向不同内存区域...), &a); 违背 strict aliasing,编译认为 argv1,argv2 指向不同内存区域 ,为未定义行为(UB,Undefined Behavior)。...在 C11 标准 3.4.3 小结对未定义行为进行了明确定义: 未定义行为:当使用不可移植或者错误程序/错误数据,将导致不可预期结果。典型例子就是整数溢出行为。

43610

C++最佳实践 | 2. 代码风格

使用nullptr C++11引入了nullptr表示空指针,应该用来代替0或NULL来指示空指针。 注释 注释块应该使用//,不是/* */,使用//可以更容易在调试注释掉代码块。...用大括号初始化默认值 用大括号初始化不允许在编译截断数据长度。.... // 除非有明确理由,否则优先使用{}初始化不是=。 忘记初始化成员会导致未定义行为错误,而这些错误通常很难发现。 如果成员变量在初始化后不会更改,则将其标记为const。...,否则不提供编译可以提供任何函数(拷贝构造函数、拷贝赋值操作符、移动构造函数、移动赋值操作符、析构函数)。...目标是让编译提供在添加更多成员变量自动维护最佳版本。 这篇文章介绍这一原则背景,并解释几乎可以覆盖所有情况实现技术: C++'s Rule of Zero[19]。

1.1K10

《逆袭进大厂》第三弹之C++提高篇79问79答

函数指针指向是特殊数据类型,函数类型是由其返回数据类型和其参数列表共同决定函数名称则不是其类型一部分。...然而当实现该模板.cpp文件中没有用到模板实例编译懒得去实例化,所以,整个工程.obj中就找不到一行模板实例二进制代码,于是连接也黔驴技穷。...因为在编译模板并不能生成真正二进制代码,而是在编译调用模板类或函数CPP文件才会去找对应模板声明和实现,在这种情况下编译是不知道实现模板类或函数CPP文件存在,所以它只能找到模板类或函数声明找不到实现...编译会一一操作初始化列表,以适当顺序在构造函数之内安插初始化操作,并且在任何显示用户代码前。...sizeof(p),p 为指针得到是一个指针变量字节数,不是p 所指内存容量。 3) 编译为了简化对数组支持,实际上是利用指针实现对数组支持。

2.2K30

【Linux】内存检测工具Valgrind

等分配动态内存范围 读/写不适当栈中内存块 内存泄漏,指向一块内存指针丢失 不正确malloc/free或new/delete匹配 memcpy()相关函数dst和src指针重叠问题 ---...- Memcheck检查步骤及注意事项 在编译程序时候打开调试模式(gcc编译-g选项),以便显示行号,编译去掉-O1 -O2等优化选项,检查是C++程序时候,考虑加上选项:-fno-inline...---- 结果分析 Valgrind(memcheck)包含这7类错误 illegal read/illegal write errors —— 非法读取/非法写入错误 use of uninitialised...,还有机会使用或者释放,指针指向动态内存还没有被释放就退出了 Definitely lost —— 确定内存泄露,已经不能够访问这块内存 Indirectly lost —— 指向该内存指针位于内存泄露处...Possibly lost —— 可能内存泄露,仍然存在某个指针能够访问某块内存,但该指针指向已经不是该内存首位置 Suppressed —— 某些库产生错误不予以提示,这些错误会被统计到suppressed

2.8K10

读完某C++神作,我只记下了100句话

普通引用不能初始化为常量,const引用可以。 typedef用来定义类型同义词。 头文件用于声明,不是定义,因而可以出现多次。定义语句不应该放在头文件里,出现两次会导致多重定义链接错误。...静态变量只在初次调用时初始化,static size_t ctr=0只执行一次。 内联函数避免函数调用开销:编译展开为函数体中表达式,免去函数调用寄存保存恢复、复制实参跳转等。...初始化const或引用类型或没有默认构造函数类类型数据成员唯一机会是构造函数初始化列表【冒号开始,逗号分隔】。初始化顺序由定义顺序决定,不是初始化列表顺序。...即使定义其他构造函数,也会合成复制构造函数【能够复制类中数组】。类成员有指针一般需要显示定义复制构造函数。 声明不定义成员函数是合法,但是使用将导致链接失败。...派生类指针静态类型和动态类型不一致【基类指针指向派生类是】,为保证删除指针调用合适析构函数【多态】,基类析构必须为virtual。

1.4K20

C++11『基础新特性』

即可 以下是不同编译对 C++11 语法支持情况(绿色表示最低支持版本,红色表示不支持) 主流编译有:GCCClang、MSVC,其中 GCC 就是在 Linux 中使用编译,基本上...GCC 4.6 及后续版本就能对 C++11 进行很好支持, MSVC 是微软 VS 系列编译,从 VS 2015 及后续版本对 C++11 语法支持较好 推荐使用 VS 2019 或 VS...,这对于编码初始化是十分友好 2.1.对于内置类型 首先需要明白,为了适应 泛型编程,C++ 中内置类型(比如 int、double 等)就已经全部配备 构造函数,方便在进行模板传参,传递默认构造值...int m, int y) :_day(d), _month(m), _year(y) {} 接下来同样代码,尝试编译,结果出现错误 现在情况是 d1 列表初始化失败,d2 列表初始化成功 这是因为...d1 是由 构造 + 赋值 优化后进行构造, explicit 关键字可以杜绝编译这种 隐式 优化行为,编译无法优化,也就无法构造 d1 d2 相当于直接调用了 拷贝构造函数,不受优化影响

21340

《Effective C++》学习笔记

构造函数使用成员初始化列表来赋值,不是在构造函数里去赋值(会导致赋值两次,浪费了),列表排列次序保持和class中声明次序一致。...,且只有两个指针都销毁才delete,auto_ptr只会保证一个指针有效,在复制,原指针指向null。...不要只因为模板函数出现在头文件,就将它们声明为inline,模板函数和inline并不是必须结对出现。...做法是声明一个泛化构造函数,也就是定义一个模板构造函数,接收模板参数,声明一个指向真实对象指针,声明一个获取该对象指针get函数,用该get函数放在初始化列表中来构造模板类。...这样就能使用一种类型特化出自制智能指针来构造另一种类型特化出自制智能指针。同时,在初始化列表编译会为你检查是否允许该类型转换(比如只允许子类往父类转换,不能相反)。

1.1K20

重温 CC++ 笔记

运行在编译阶段,只能看到编译常数和类型,看不到运行时变量、指针、内存数据等, (__visibility__("default"): 某个符号是否导出 试想这样情景,程序调用某函数A,A函数存在于两个动态链接库...赋值初始化或者花括号初始化初始化列表、Initializer list),变量右边必须要有一个表达式(简单、复杂都可以) 很容易理解,只是声明,没有赋值,无法推导类型。...指针是内存地址,引用是变量别名,指针可以是空,引用不能为空(引用必须初始化,否则编译失败) 引用是通过指针常量实现 指针完全映射了计算机硬件,操作效率高,是 C++ 效率高根源。...不会带病工作 使用范围更广,比如没有返回值函数出现异常 使用 noexcept 修饰不会抛出异常函数,方便编译做优化: noexcept 真正意思是:“我对外承诺不抛出异常,我也不想处理异常...lambda 保存定义捕获外部变量,就可以跳离定义点,把这段代码“打包”传递到其他地方去执行 在 C++ 里,每个 lambda 表达式都会有一个独特类型,而这个类型只有编译才知道,

1.2K30
领券