C++ 简单 IF 子句更改静态 const char 变量的值

C++ Simple IF clause changes value of a static const char variable

好的,我已经处理了两天了,我找不到解决方案。

问题: 我正在尝试使用 Winapi 为 文件选择对话框 设置过滤器。我正在使用 GetOpenFileName 函数来执行此操作。此函数使用 结构 来设置选项,例如文件扩展名过滤器。这个名为 lpstrFilter 的结构成员需要特定的字符串格式。我完全按照 Winapi 指示设置该字符串,但由于某种原因,该字符串的值发生了变化。

我有这个 static const char *:

//This contains string "JPG"
static const char * extensionFilter = v->trabajo10.C_JMV_SelectFile_FileExtension7.GetString();

//This forms a filter string which applies to OPENFILENAME structure.
string sFilter;
sFilter.append("Format: ");
sFilter.append(extensionFilter);
sFilter.push_back('[=10=]');
sFilter.append("*.");
sFilter.append(extensionFilter);
sFilter.push_back('[=10=]');
const char * filter = sFilter.c_str();
ofn.lpstrFilter = filter; //This sets: --> Format: JPG[=10=]*.JPG[=10=]

//This opens the file selection dialog
if (GetOpenFileName(&ofn)==TRUE){
...

文件选择对话框看起来正确,如下所示:

笑话来了,我把代码修改成这样:

//This contains string "JPG"
static const char * extensionFilter = v->trabajo10.C_JMV_SelectFile_FileExtension7.GetString();

if(1){
   //This forms a filter string which applies to OPENFILENAME structure.
   string sFilter;
   sFilter.append("Format: ");
   sFilter.append(extensionFilter);
   sFilter.push_back('[=11=]');
   sFilter.append("*.");
   sFilter.append(extensionFilter);
   sFilter.push_back('[=11=]');
   const char * filter = sFilter.c_str();
   ofn.lpstrFilter = filter; //This sets: --> Format: JPG[=11=]*.JPG[=11=]
}

//This opens the file selection dialog
if (GetOpenFileName(&ofn)==TRUE){
...

这就是结果,问题所在

过滤字符串被修改了???

if(1){
   //This forms a filter string which applies to OPENFILENAME structure.
   string sFilter;
   sFilter.append("Format: ");
   sFilter.append(extensionFilter);
   sFilter.push_back('[=10=]');
   sFilter.append("*.");
   sFilter.append(extensionFilter);
   sFilter.push_back('[=10=]');
   const char * filter = sFilter.c_str();
   ofn.lpstrFilter = filter; //This sets: --> Format: JPG[=10=]*.JPG[=10=]
}

sFilter 变量的生命周期在它声明的块结束时结束。 sFilter.c_str()返回的指针在sFilter被修改或销毁之前一直有效。

您在该指针失效后使用它。这与您昨天遇到的问题相同,我在对该问题的评论中猜到了。这就是为什么您需要展示完整的 MCVE。这个问题看起来也与您一周前提出的问题重复:。我建议您花一些时间来确保您完全理解 c_str().

返回值的有效性

您必须确保 sFilter 在您使用完指针之前一直存在。在外部块中声明 sFilter 以确保。

问题是您有一个超出范围的变量

if(1){
   string sFilter;

   // ... code

   // Right here
   const char * filter = sFilter.c_str();      
   ofn.lpstrFilter = filter;
}

该块结束后 filter 超出范围,因此 ofn.lpstrFilter 有一个悬空指针。

回答 ProtectedVoid 对声明未使用对象的担忧:想象一下 std::string 是一个昂贵的对象并且这种情况不太可能发生。除非条件为真,否则您不希望构造对象。但它必须持续超出条件的范围。所以我们使用默认构造的 unique_ptr 比默认构造的 string:

便宜得多的事实
std::unique_ptr<std::string> scope_extender;
if( something unlikely ){
       //This forms a filter string which applies to OPENFILENAME structure.
       std::string* sFilter = new std::string;
       scope_extender.reset( sFilter );
       sFilter->append("Format: ");
       sFilter->append(extensionFilter);
       sFilter->push_back('[=10=]');
       sFilter->append("*.");
       sFilter->append(extensionFilter);
       sFilter->push_back('[=10=]');
       const char * filter = sFilter->c_str();
       ofn.lpstrFilter = filter; //This sets: --> Format: JPG[=10=]*.JPG[=10=]
    }

显然,我不想暗示 std::string 的建造成本足够高,值得所有这些麻烦。但是在类似情况下的某些对象可能是。此外,有人评论说如果一个条件中有许多次要对象会怎样。在这种情况下,您需要一个实用程序结构将它们全部保存在一起,并且 unique_ptr 有条件地拥有该结构。