使用智能指针

Using Smart Pointers

本文关键字:指针 智能      更新时间:2023-10-16

我正在开发一个具有以下功能的旧C++应用程序,

char* CreateNewString (const char* node)
{
int len = (int) strlen(node) + 1;
char * ptr = new char [len];
strcpy_s(ptr, len, node);
return ptr;
}

此函数是从应用中的许多类调用的,下面是一个示例用例。

char * nodeID = obj.CreateNewString(process->GetNodeID());

应用调用不同的进程并获取节点 ID 作为字符指针,然后将其传递给CreateNewString函数,以便为新字符串动态分配内存。

在上述调用之后,应用程序中没有任何地方,它正在删除内存。据我观察,这里有明确的内存泄漏。

我认为解决这个问题的方法很少。但我想先探索使用 C++11 中的智能指针,然后再尝试其他任何内容。

我尝试过:

所以我想出了以下功能:

char* CreateNewString (const char* node) 
{
int len = (int) strlen(node) + 1;
shared_ptr<char> ptr (new char [len](), [](char* p) {delete [] p;});
strcpy_s(ptr.get(), len, node);
return ptr.get();
}

目标是保持函数签名相同,即它返回一个 char 指针,这样我就不必在所有调用位置进行更改。

上述内容不起作用,因为ptr已释放,因为它是在此函数范围内声明的。

我的目标是:

  1. 使用 C++ 11 个智能指针来实现此目的,只需对现有应用程序进行最少的代码更改。

我知道的另一种方法是在调用位置本身时动态初始化数组,然后在该作用域结束之前将其删除。但我想在回到传统的C++方式之前探索新的C++功能。顺便说一句,我现在对探索std::string不感兴趣。

你可以:

  • 返回shared_ptr
  • 返回std::string
  • 保持一切原样

这些是你的选择。

我没有看到可以让函数返回字符指针并仍然使用智能指针的方法。完成它可能会有潜在的黑客攻击,但所有这些都有开销,更重要的是,不必要的代码。我的建议是对你编写的新功能进行简单的更改,然后在所有调用位置进行另一个更简单的更改。

所以函数看起来像这样,

shared_ptr<char> CreateNewString (const char* node) 
{
int len = (int) strlen(node) + 1;
shared_ptr<char> ptr (new char [len](), [](char* p) {delete [] p;});
strcpy_s(ptr.get(), len, node);
return ptr;
}

然后在任何地方调用它,只需添加一个.get()

char * nodeID = obj.CreateNewString(process->GetNodeID()).get();

这是一种黑客攻击,但它会起作用,并且您不会有内存泄漏。 您可以做的是添加智能指针的静态向量,然后在调用函数时将指针存储在向量中,这样它就不会在函数末尾超出范围。 那看起来像

char* CreateNewString (const char* node) 
{
std::size_t len = strlen(node) + 1;
static std::vector<std::unique_ptr<char[]>> data_pool; // static pool, destroyed at end of program
data_pool.push_back(std::unique_ptr<char[]>(new char [len]{})); // add pointer to pool
strcpy_s(data_pool.back().get(), len, node); // copy the string
return data_pool.back().get(); // return pointer to the managed data
}

使用std::unique_ptr,它可以正确删除数组,因此我们不需要自定义删除器

请注意,使用此解决方案不会有内存泄漏,但所有分配的内存将持续到程序结束。 你没有获得任何东西,但至少你可以保证在程序终止之前释放内存。