C++ 确保在C+中编译时使用正确的双指针传递方法+;

C++ 确保在C+中编译时使用正确的双指针传递方法+;,c++,pointers,parameters,compiler-warnings,C++,Pointers,Parameters,Compiler Warnings,在过去,我们在软件中遇到各种内存泄漏。我们发现发生这些情况的主要原因是我们自己的“free”方法使用不当,这些方法释放队列消息数据等 问题是,在我们最深的工具函数中,有两种方法可以释放动态分配的内存,其特征如下: 无无效(无效*数据) 无作废(作废**ppData); 这两种方法基本上做相同的事情,除了第二种方法首先取消数据引用。我知道用这两种软件中的一种做任何事情都是可能的,但是我们可以说,软件在很多年前就是这样设计的,现在到处都有使用这两种软件的代码 当有人实现对以下方法的调用时,问题就

在过去,我们在软件中遇到各种内存泄漏。我们发现发生这些情况的主要原因是我们自己的“free”方法使用不当,这些方法释放队列消息数据等

问题是,在我们最深的工具函数中,有两种方法可以释放动态分配的内存,其特征如下:


无无效(无效*数据)
无作废(作废**ppData);

这两种方法基本上做相同的事情,除了第二种方法首先取消数据引用。我知道用这两种软件中的一种做任何事情都是可能的,但是我们可以说,软件在很多年前就是这样设计的,现在到处都有使用这两种软件的代码

当有人实现对以下方法的调用时,问题就出现了:


队列消息*pMsg
pMsg=myQueue.read(…);//动态为消息分配空间并填充它
//做点什么
myQueue.free(&pMsg)/尝试模板:

template <class T> void free (T *pData);
template <class T> void free (T **ppData);
编辑:那么原始版本中发生了什么

重载函数解析的规则相当复杂,但原则上,编译器首先尝试为参数类型找到精确的数学表达式,如果找不到,则可以应用各种自动类型转换

其中一种自动类型转换是,任何指针(包括指向指针的指针)都可以转换为
void*
指针。但是,没有规则规定键入的指向指针(
T**
)可以自动转换为指向指针的无效指针(
void**
)。这就是为什么您的所有呼叫都将被
释放(void*)

当您引入模板化版本时,这会发生变化。编译器现在可以为您所做的每个调用找到一个精确的匹配项--
free(T*)
free(T**)
--这使它能够调用正确的版本。

尝试模板:

template <class T> void free (T *pData);
template <class T> void free (T **ppData);
编辑:那么原始版本中发生了什么

重载函数解析的规则相当复杂,但原则上,编译器首先尝试为参数类型找到精确的数学表达式,如果找不到,则可以应用各种自动类型转换

其中一种自动类型转换是,任何指针(包括指向指针的指针)都可以转换为
void*
指针。但是,没有规则规定键入的指向指针(
T**
)可以自动转换为指向指针的无效指针(
void**
)。这就是为什么您的所有呼叫都将被
释放(void*)


当您引入模板化版本时,这会发生变化。编译器现在可以为您进行的每个调用找到一个精确的匹配项--
free(T*)
free(T**)
--这使它能够调用正确的版本。

非常好+1:这些可以与其他声明一起添加到标题中,并让它们为您执行强制转换-也许您可以添加一些简单的定义来显示对其他函数的调用。您,先生,刚刚度过了我的一天!这是完美的,它比我预想的还要好,它不会产生警告,它只会解决由于编程错误而发生的所有内存泄漏。非常感谢!不过有一个问题,我不完全理解这句话。这个模板构造真的有意义吗?还是它只是一条空指令,告诉编译器仔细查看参数类型?很抱歉延迟了--我已经在答案中添加了一个解释,以澄清最初的情况以及模板版本对此的更改。非常好+1:这些可以添加到标题包含其他声明,并让它们为您执行强制转换-也许您可以添加一些简单的定义来显示对其他函数的调用。您,先生,刚刚度过了我的一天!这是完美的,它比我预想的还要好,它不会产生警告,它只会解决由于编程错误而发生的所有内存泄漏。非常感谢!不过有一个问题,我不完全理解这句话。这个模板构造实际上有什么意义吗?或者它只是一条空指令,告诉编译器仔细查看参数类型?很抱歉延迟了--我已经在答案中添加了一个解释,以澄清最初的情况以及模板版本对此的更改。