【问题标题】:Multiple std::string temporaries resulting in the same c_str pointer多个 std::string 临时变量导致相同的 c_str 指针
【发布时间】:2017-09-19 19:45:05
【问题描述】:

我有一个返回std::string 的函数。我将它传递给printf 并创建了一个辅助函数,该函数使用公共参数调用该函数并返回std::string 中的c 字符串指针。每次通话我都会得到相同的指针。我认为这与临时寿命有关。如果可能的话,我想解决这个问题并使其安全。

#include <stdio.h>
#include <string>

std::string intToString(int num) {
  char buf[100];
  snprintf(buf, sizeof(buf), "%d", num);
  return buf;
}

const char *helper(int num, int increment) {
  return intToString((num + increment) * 10).c_str();
}

int main() {
  for (int i=1; i < 5; i++) {
    printf("- %d: %3s  %3s  %3s  %3s\n", i,
           intToString((i + 0) * 10).c_str(),
           intToString((i + 1) * 10).c_str(),
           intToString((i + 2) * 10).c_str(),
           intToString((i + 3) * 10).c_str()
           );
    printf("+ %d: %3s  %3s  %3s  %3s\n", i,
           helper(i, 0),
           helper(i, 1),
           helper(i, 2),
           helper(i, 3)
           );
  }
  return 0;
}

输出:

- 1:  10   20   30   40
+ 1:  10   10   10   10
- 2:  20   30   40   50
+ 2:  20   20   20   20
- 3:  30   40   50   60
+ 3:  30   30   30   30
- 4:  40   50   60   70
+ 4:  40   40   40   40

【问题讨论】:

  • return intToString((num + increment) * 10).c_str(); - 支持该指针的std::string 在调用者获得地址时已经消失。您的程序调用未定义的行为。第一种情况下临时的生命周期延长。在第二种情况下,唯一临时保留的是一个悬空指针。

标签: c++ stdstring temporary


【解决方案1】:

c_str()的返回值只有在字符串对象存在且未被修改的情况下才有效。像在helper 中那样从临时返回它是不正确的。改为返回 std::string,并仅在您实际需要将其用作 c 字符串的站点使用 c_str()

供参考:http://www.cplusplus.com/reference/string/string/c_str/

【讨论】:

    【解决方案2】:

    这是仅使用 c++ 对象和流的等效代码:

    #include <iostream>
    #include <string>
    #include <iomanip>
    
    std::string helper(int num, int increment) {
      return std::to_string((num + increment) * 10);
    }
    
    int main() {
      for (int i=1; i < 5; i++) {
          std::cout << "- " << i 
          << ": " << std::setw(3) << std::to_string((i + 0) * 10)
          << "  " << std::setw(3) << std::to_string((i + 1) * 10)
          << "  " << std::setw(3) << std::to_string((i + 2) * 10)
          << "  " << std::setw(3) << std::to_string((i + 3) * 10)
          << '\n'; 
    
          std::cout << "+ " << i 
          << ": " << std::setw(3) << helper(i, 0)
          << "  " << std::setw(3) << helper(i, 1)
          << "  " << std::setw(3) << helper(i, 2)
          << "  " << std::setw(3) << helper(i, 3)
          << '\n'; 
      }
      return 0;
    }
    

    预期输出:

    - 1:  10   20   30   40
    + 1:  10   20   30   40
    - 2:  20   30   40   50
    + 2:  20   30   40   50
    - 3:  30   40   50   60
    + 3:  30   40   50   60
    - 4:  40   50   60   70
    + 4:  40   50   60   70
    

    【讨论】:

      猜你喜欢
      • 2012-04-17
      • 1970-01-01
      • 2022-10-27
      • 1970-01-01
      • 2013-10-19
      • 1970-01-01
      • 2020-12-18
      • 1970-01-01
      • 2018-03-07
      相关资源
      最近更新 更多