【问题标题】:Remove delete/delete[]删除删除/删除[]
【发布时间】:2013-08-31 16:21:20
【问题描述】:

我正在尝试删除旧应用程序的所有 delete 和 delete[] 并改用智能指针。在下面的代码 sn-p 中,我想删除最后一个 for cicle。

std::unique_ptr<MapiFileDesc> fileDesc(new MapiFileDesc[numFiles]);

for (int i = 0; i < numFiles; ++i)
{
    // Works but I've to delete[] at the end
    fileDesc[i].lpszPathName = new CHAR[MAX_PATH];

    // Does not work. For each iteration the previous array will be deleted
    // It also happens with shared_array
    boost::scoped_array<CHAR> pathName(new CHAR[MAX_PATH]);
    fileDesc[i].lpszPathName = pathName.get();
}

// I want to remove the following cicle
for (int i = 0; i < numFiles; ++i)
{
    delete [] fileDesc[i].lpszPathName;
    fileDesc[i].lpszPathName = nullptr;
}

对于这种情况,你认为最好的方法是什么:使用一个包装对象来跟踪所有创建的数组并在析构函数中删除它们,或者使用 boost::shared_array 的向量并将它们分配给每个要素?

std::vector<boost::shared_array<CHAR> > objs;

for (int i = 0; i < 10; ++i)
{
    objs.push_back(boost::shared_array<CHAR>(new CHAR[MAX_PATH]));
}

我需要使用 boost::shared_ptr,因为我使用的是 VC++ 2008

提前致谢。 J. Lacerda

【问题讨论】:

  • 使用std::string
  • 如果你使用new[]进行分配,你需要std::unique_ptr&lt;MapiFileDesc[]&gt;。但是,是的,请改用std:string
  • @juanchopanza 只是为了好奇,这是 C++11 唯一的语法,还是也可以与(旧的)std::auto_ptr 一起正常工作?
  • 对不起。输入时出错。
  • @g-makulik 我认为它不适用于auto_ptr

标签: c++ visual-c++ memory-management smart-pointers raii


【解决方案1】:
std::vector<std::string > objs(numFiles, std::string(MAX_PATH, 0));
std::vector<MapiFileDesc> fileDesc(numFiles);
for (int i = 0; i < numFiles; ++i)
    fileDesc[i].lpszPathName=objs[i].data();
// after the C API calls, if you do need to use the strings as C++ strings,
// resync the C++ string length with the C string data
// (not necessary if you just use them via c_str())
for (int i = 0; i < numFiles; ++i)
    objs[i].resize(strlen(objs[i].c_str());

顺便说一句,如果您不需要将整个数组传递给 C API,而只需传递单个结构,则可以创建一个结构的单个向量,该向量同时存储 MapiFileDesc 结构和 std::string,绑定强烈的两个对象的生命周期,并允许构造函数负责链接lpszPathName 与字符串data() 成员;不过,如果仅在单个函数中使用此结构,我可能不会打扰。

【讨论】:

  • +1 以获得实际提供具体解决方案的答案:)
【解决方案2】:
std::unique_ptr<MapiFileDesc[]> fileDesc(new MapiFileDesc[numFiles]);
typedef std::unique_ptr<CHAR[]> CharBuffer;
std::vector<CharBuffer> pathNameBuffers;

for (int i = 0; i < numFiles; ++i)
{
    pathNameBuffers.push_back(CharBuffer(new CHAR[MAX_PATH]));
    fileDesc[i].lpszPathName = pathNameBuffers.back().get();
}

虽然这不会使最后的指针无效。

【讨论】:

  • 但是当函数终止时它会释放分配的内存,对吧?
  • 是的,pathNameBuffers 超出范围的那一刻。 (说到这里,如果可能的话,你应该在 before fileDesc 之前声明它,这样字符串的寿命就会比指针长。)
【解决方案3】:

在尝试减少指针数量/摆脱丑陋的内存管理时,减少 deletedelete[] 调用的数量并不是您唯一可以做的事情。

标准库提供了许多简洁的类,允许您使用具有自动存储持续时间的对象。使用 std::vector 等 STL 容器代替 C 样式的数组,对于语义上表示字符串的字符数组,请相应地使用 std::stringstd::wstring

【讨论】:

    【解决方案4】:

    我喜欢 boost 共享数组的方法。我认为你面临的问题是 boost shared_array 中的 get () 方法没有增加对象的引用计数。这是您示例中的一种解决方法,它将增加引用计数。

    for (int i = 0; i < numFiles; ++i)
    {
        // Works but I've to delete[] at the end
        fileDesc[i].lpszPathName = new CHAR[MAX_PATH];
    
        // Does not work. For each iteration the previous array will be deleted
        // It also happens with shared_array
        boost::shared_array<CHAR> pathName(new CHAR[MAX_PATH]);
        fileDesc[i].lpszPathName = pathName.get();
    
        **// Here is a workaround to increase reference count
        boost::shared_array<CHAR> pathNameTemp (pathName);**
    }
    

    【讨论】:

    • 循环结束后,引用计数为1,fileDesc被销毁,内存将被删除。
    猜你喜欢
    • 2022-07-22
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 2012-01-03
    • 2011-05-14
    相关资源
    最近更新 更多