使用指针作为函数的普通变量返回后如何删除指针

问题描述 投票:0回答:2

我看过类似的问题,但它们都假设返回类型也是一个指针。如果这措辞不好,我深表歉意,因为我对 C++ 有点陌生。

所以我有以下功能:

//Converts string to LPCTSTR for dialog box
LPCTSTR CAnotherAttemptDlg::convertToLPCTSTR(std::string conversion)
{

    size_t convertedChars = 0;
    const size_t newsizew = conversion.size() + 1;
    wchar_t* wcstring = new wchar_t[newsizew];
    mbstowcs_s(&convertedChars, wcstring, newsizew, conversion.c_str(), _TRUNCATE);
    return wcstring;

}

我确信您注意到我返回一个指针作为结果,但是输出不应该是指针,因此我无法通过删除分配给它的指针来删除函数外部的指针,因为它不输出到指针。最好的方法是什么?

注意:以防万一有人问我这是做什么的,它将字符串转换为 LPCTSTR,这与 wchar_t* 相同

编辑: 为了澄清起见,这是调用此函数的块:

BOOL CAnotherAttemptDlg::OnInitDialog()
{

    string settingsLine;
    LPCTSTR defStrPath = L""; // = "C:\\Ste\\Runtime\\TestFiles";
    LPCTSTR defEndPath = L"";

    //grabs default start and end paths from FileTrams.ini, parses it into proper variables
    ifstream settingsStream("FileTrans.ini");

    while (getline(settingsStream, settingsLine)) {
        string delimiter = "=";
        string tokenOne = settingsLine.substr(0, settingsLine.find(delimiter)); 
        string tokenTwo = settingsLine.substr(settingsLine.find(delimiter) + 1, '10');

        if (tokenOne == "startPath") {
            defStrPath = convertToLPCTSTR(tokenTwo);
        }
        else if (tokenOne == "endPath") {
            defEndPath = convertToLPCTSTR(tokenTwo);
        }

    }

    

    settingsStream.close();
    


    CDialogEx::OnInitDialog();

    SetWindowLong(this->m_hWnd, GWL_STYLE, GetWindowLong(this->m_hWnd, GWL_STYLE) |  WS_SYSMENU);

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    // TODO: Add extra initialization here
    
    SetDlgItemText(IDC_MFCEDITBROWSE1, defStrPath);
    SetDlgItemText(IDC_MFCEDITBROWSE2, defEndPath);

    return TRUE;  // return TRUE  unless you set the focus to a control

    delete[] defStrPath;
    delete[] defEndPath;
}
c++ string pointers memory-management memory-leaks
2个回答
0
投票

因此,在一些人的帮助下,我已经让程序正常运行,没有内存泄漏。建议使用 wstring 而不是 LPCTSTR,因为它会自行释放。

这是当前代码:

BOOL CAnotherAttemptDlg::OnInitDialog()
{

    string settingsLine;
    wstring defStrPath = L""; // = "C:\\Ste\\Runtime\\TestFiles";
    wstring defEndPath = L"";

    //grabs default start and end paths from FileTrams.ini, parses it into proper variables
    ifstream settingsStream("FileTrans.ini");

    while (getline(settingsStream, settingsLine)) {
        string delimiter = "=";
        string tokenOne = settingsLine.substr(0, settingsLine.find(delimiter)); 
        string tokenTwo = settingsLine.substr(settingsLine.find(delimiter) + 1, '10');

        if (tokenOne == "startPath") {
            defStrPath = convertToLPCTSTR(tokenTwo);
        }
        else if (tokenOne == "endPath") {
            defEndPath = convertToLPCTSTR(tokenTwo);
        }

    }

    

    settingsStream.close();
    


    CDialogEx::OnInitDialog();

    SetWindowLong(this->m_hWnd, GWL_STYLE, GetWindowLong(this->m_hWnd, GWL_STYLE) |  WS_SYSMENU);

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    // TODO: Add extra initialization here
    
    SetDlgItemText(IDC_MFCEDITBROWSE1, defStrPath.c_str());
    SetDlgItemText(IDC_MFCEDITBROWSE2, defEndPath.c_str());

    return TRUE;  // return TRUE  unless you set the focus to a control

}

std::wstring CAnotherAttemptDlg::convertToLPCTSTR(std::string conversion)
{
    wstring temp = L"";

    size_t convertedChars = 0;
    const size_t newsizew = conversion.size() + 1;
    wchar_t* wcstring = new wchar_t[newsizew];
    mbstowcs_s(&convertedChars, wcstring, newsizew, conversion.c_str(), _TRUNCATE);
    temp = wcstring;
    delete[] wcstring;
    return temp;

}

需要指出的一个错误是,wstring 在使用 nullptr 时似乎会出错,因此我只是用空白字符串进行初始化,这可能不是最好的,但目前可以使用。


0
投票

我对你问题的回答是双重的......

从技术上讲:你可以
delete[]

正如 @someprogrammerdude 和其他人指出的那样,您的方法返回的是指向新分配的 wchar_t 序列的指针:一个 LPCWSTR,即指向 Const Wchar“STRing”的(长)指针。您可以将

delete[]
应用于此方法的调用结果。

但我真正想告诉你的是:

通常:不要这样做。

有多种原因导致您不应该编写这样的函数或方法:

  1. 当不是绝对必要时,您应该避免使用原始的

    new
    delete
    ;这是 C++ 核心指南 R.11。一个主要原因是,很容易忽视
    delete
    您使用原始
    new
    分配的内容,并且没有自动机制来确保您这样做。

  2. 您还应该避免“拥有”内存的原始指针;这是 C++ 核心指南 R.3。具体来说,您的函数或方法签名不应通过返回返回指针(您的函数会这样做)来产生所有权。相反,

  3. 使用...RAII自动管理内存;这是 C++ 核心指南R.1。通常,这意味着类在构造时分配资源并在销毁时释放资源。对于字符串,具体而言,

  4. 如果您需要为字符串字符提供灵活的缓冲区而不是

    std::string
    - 使用适当的缓冲区类
    std::vector
    ,甚至可能是
    std::stringstream
    ,具体取决于上下文。

  5. 但实际上 - 你的对话类没有必要转换人们的字符串!毕竟,不知道

    conversion
    参数是类实例所关心的任何字符串。如果您希望能够将
    char
    字符串转换为
    wchar_t
    字符串 - 这当然是可能的。阅读这个 StackOverflow 问题:

    C++ 将字符串(或 char*)转换为 wstring(或 wchar_t*)

    你会找到一个足够简单的答案(最初来自这里):

    std::wstring utf8_string_to_wstring(const std::string& str) {
        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
        return converter.from_bytes(str);
    }
    

    这适用于 UTF-8 文本,特别是 ASCII 文本。

© www.soinside.com 2019 - 2024. All rights reserved.