我看过类似的问题,但它们都假设返回类型也是一个指针。如果这措辞不好,我深表歉意,因为我对 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;
}
因此,在一些人的帮助下,我已经让程序正常运行,没有内存泄漏。建议使用 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 时似乎会出错,因此我只是用空白字符串进行初始化,这可能不是最好的,但目前可以使用。
我对你问题的回答是双重的......
delete[]
它正如 @someprogrammerdude 和其他人指出的那样,您的方法返回的是指向新分配的 wchar_t 序列的指针:一个 LPCWSTR,即指向 Const Wchar“STRing”的(长)指针。您可以将
delete[]
应用于此方法的调用结果。
但我真正想告诉你的是:
有多种原因导致您不应该编写这样的函数或方法:
当不是绝对必要时,您应该避免使用原始的
new
和delete
;这是 C++ 核心指南 R.11。一个主要原因是,很容易忽视 delete
您使用原始 new
分配的内容,并且没有自动机制来确保您这样做。
您还应该避免“拥有”内存的原始指针;这是 C++ 核心指南 R.3。具体来说,您的函数或方法签名不应通过返回返回指针(您的函数会这样做)来产生所有权。相反,
使用...RAII自动管理内存;这是 C++ 核心指南R.1。通常,这意味着类在构造时分配资源并在销毁时释放资源。对于字符串,具体而言,
如果您需要为字符串字符提供灵活的缓冲区而不是
std::string
- 使用适当的缓冲区类 std::vector
,甚至可能是 std::stringstream
,具体取决于上下文。
但实际上 - 你的对话类没有必要转换人们的字符串!毕竟,不知道
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 文本。