[笔记]c++ 常见问题

简介: [笔记]c++ 常见问题

通用问题

一、结构体用char*,char[],还是string?

在 C++ 编程中,领导坚持用 char 而不用 string,string 有那么可怕吗? - 包包包子的回答 - 知乎

1.1.对外提供接口情况时 使用char[]最好

  1. 不让用string 很多的是考虑 api接口的简洁,兼容性。dll 导出 stl 这种模板库 简直是灾难,很不好解决。而且要考虑内存分配与释放问题,必须在同一个模块进行,跨dll要出问题的。 导出dll 一般都用 c风格的api 这样客户也好理解,避免各种问题。
  2. string在c++标准中自定义了接口,没有定义具体实现,各标准库对他的实现不一。
  3. 跨平台一般是C风格接口更容易被其他平台调用
  4. 跨平台返回std::string 容易产生跨dll释放问题

1.2 对内 业务上尽量使用string

业务上肯定要string,毕竟string好使,尽量用引用,这样能减少内存拷贝,而且在客户端编程里面,string肯定非常常用。虽然客户端没有高性能要求,但还是要注意性能,我见过很多项目,项目代码量不大,但是就是很卡。

二、MAX_PATH为啥是260?

MFC 中_MAX_PATH的理解

解决路径超过MAX_PATH问题

三、指针

3.1 二级指针和指针数组

二级指针:指向一堆一级指针起始地址的指针,只是指针 4个字节 32位大小,没有创建任何空间,所以里面内容需要每次new,一级指针内容也需要new。

指针数组:存放一级指针数组,有一段有限内存存放若干数量的指针,n个4个字节的指针,但每个一级指针的内容需要new出来。

void GetIntArr(int ** &ppInt,int &size) 
{
  size = 10;
  ppInt = new int*[size];
  for (size_t i = 0; i < size; i++)
  {
    ppInt[i] = new int;
    *(ppInt[i]) = i;
  }
}
void main(void)
{
  int **ppInt = NULL;
  int size = 0;
  GetIntArr(ppInt,size);
  for (size_t i = 0; i < size; i++)
  {
    printf("%d\n", *ppInt[i]);
  }
  system("pause");
}

三、std::string重复销毁问题

3.1 起因:用string作为外部接口

四、返回引用函数 引用作用范围结束后会调用析构函数

五、Debug\Release 导致运行结果不同

5.1 起因:结构体没进行构造初始化

Debug可能默认是0值

Release默认是随机值

六、long和longlong长度

longlong 类型 http://c.biancheng.net/view/7809.html

建议用stdint.h 跨平台类型

建议用void* 作为map的key 因为 程序多少位

七、std容器常见问题

7.1 std::map

map 通过键值查找,判空问题

正确示范

std::map mapTest;
...
if(mapTest.find(element) != map.end()){
  //存在
  mapTest[key];
}

错误示范

std::map mapTest;
...
if(mapTest[key] != nullptr){
  mapTest[key];
}

原因:直接使用map[key]方式访问不管是否存在Value,都会创建一个Value,从而试判断出错。

7.2 std::vector

八、内存泄漏

8.1 代码层解决

C++代码中的内存泄漏检查如何做?(一)

1.MFC 宏 DEBUG_NEW
2.Win32 C库 Debug Routines

最重要的是 _CrtDumpMemoryLeaks使用这个函数,需要包含头文件crtdbg.h

该函数只在Debug版本才有用,当在调试器下运行程序时,_CrtDumpMemoryLeaks 将在“Output(输出)”。

3.重载new/delete
4.类似JUCE库 添加LEAKDECTOR
5. wpa 查看内存增长的exe 对应的函数

Visitual Studio

一、编译问题

1.1 error C1041: 无法打开程序数据库

error C1041: 无法打开程序数据库“xxx\vc140.pdb”;如果要将多个 CL.EXE 写入同一个 .PDB 文件,请使用/FS

原因: 项目用了同一个tmp文件夹

解决方案: 中间文件夹重命名

1.2 全局变量使用问题

无需引入头文件,只用在所引用的cpp文件前extern,引入全局变量所在头文件,会引起重复定义问题。

二、换行符问题

起因

windows创建的文件是 \n\r结束的, 而linux,mac这种unix类系统是\n结束的。

所以unix的文本到windows会出现换行丢失(ultraedit这种软件可以正确识别); 而反过来就会出现^M的符号了

windows换行是\r\n,十六进制数值是:0D0A。

LINUX换行是\n,十六进制数值是:0A

三、调试代码错位问题

起因

  1. 代码换行格式改变了,Unix(LF)的格式和Windows(CR LF)切换了导致
  2. 代码中有中文注释而又使用LF

解决办法

对应1是需要把换行改为代码默认的换行格式

对应2是把带有中文注释的地方 末尾加个 .

推荐使用dos2unix 批量转换 比较方便且中文转换过程不会乱码

四、常见警告及错误

4.1 调用socket库函数 过时

error C4996: ‘gethostbyname’: Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

解决方法1 添加宏

#define _WINSOCK_DEPRECATED_NO_WARNINGS

解决方法2 使用新的socket库函数

4.2 调用字符串库函数过时或者不安全

error C4996: ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

解决方法1 关闭警告

#pragma warning(disable:4996)

解决方法2 使用安全的字符串库函数


相关文章
|
5月前
|
算法 C++
算法笔记:递归(c++实现)
算法笔记:递归(c++实现)
|
5月前
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
|
3月前
|
C++ 容器
【C/C++笔记】迭代器
【C/C++笔记】迭代器
25 1
|
3月前
|
存储 安全 程序员
【C/C++笔记】迭代器范围
【C/C++笔记】迭代器范围
66 0
|
4月前
|
C++ Windows
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
在Windows上使用Visual Studio 2022进行FFmpeg和SDL2集成开发,首先安装FFmpeg至E:\msys64\usr\local\ffmpeg,然后新建C++控制台项目。在项目属性中,添加FFmpeg和SDL2的头文件及库文件目录。接着配置链接器的附加依赖项,包括多个FFmpeg及SDL2的lib文件。在代码中引入FFmpeg的`av_log`函数输出"Hello World",编译并运行,若看到"Hello World",即表示集成成功。详细步骤可参考《FFmpeg开发实战:从零基础到短视频上线》。
162 0
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
|
6月前
|
存储 C++ 容器
黑马c++ STL部分 笔记(7) list容器
黑马c++ STL部分 笔记(7) list容器
|
6月前
|
算法 C++ 容器
黑马c++ STL常用算法 笔记(5) 常用算术生成算法
黑马c++ STL常用算法 笔记(5) 常用算术生成算法
|
6月前
|
算法 C++ 容器
黑马c++ STL常用算法 笔记(4) 常用拷贝和替换算法
黑马c++ STL常用算法 笔记(4) 常用拷贝和替换算法
|
6月前
|
存储 算法 搜索推荐
黑马c++ STL常用算法 笔记(3) 排序算法
黑马c++ STL常用算法 笔记(3) 排序算法
|
6月前
|
算法 C++
黑马c++ STL常用算法 笔记(2) 查找算法
黑马c++ STL常用算法 笔记(2) 查找算法