【问题标题】:c++ cout and char-pointers, something I'm missing with pointersc++ cout 和 char-pointers,我缺少指针
【发布时间】:2011-12-29 11:31:14
【问题描述】:

我正在尝试为我正在制作的一种树编写一段代码,如果一个节点不存在,我想抛出一个异常,显示哪个节点不存在。即:

Trie t = Trie();
try {
    t.get('a');
} catch(NoSuchNode e) {
    cout << e.what() << endl;
}

如果节点存在,这段代码应该什么都不做,否则打印给定的错误,这是我的异常代码(我使用 std::exception,因为这似乎是个好主意):

class NoSuchNode : public std::exception
{
private:
  char *_node_name;
public:
  NoSuchNode(const char *node_name) { _node_name = new char(*node_name); }
  virtual const char* what() const throw()
    {
      std::stringstream ss;
      ss << "There exists no node for: " << _node_name << ".";
      const std::string& tmp = ss.str();
      return tmp.c_str();
    }
};

这可以正常工作,valgrind 也不会在无效读取上给出任何错误,所以我想这很好吗?现在我的问题是,在我想出这个解决方案之前,我刚刚改变了:

_node_name = new char(*node_name);

到:

_node_name = node_name;

这样我就不需要为它分配更多空间。问题是有时它并没有真正打印任何好的数据,有时是一个字符,甚至更多。不是我所期望的。此外,valgrind 抱怨说我读到了我可以使用的内存。为什么是这样?我敢打赌,如果 std::string 只是得到一个指向它认为是空终止字符串的 char 的指针,因此会尝试从内存的开头读取,直到找到空字符?这是正确的吗?解决这个问题的正确方法是什么?我应该像我所做的那样按值传递数据吗?

添加: 每个节点应该只保存一个字符,仅此而已,char 传递的所有内容都只是一个字符,仅此而已。所以可以说我没有字符中的字符串。

原来我真正感兴趣的是流如何处理 char* 输入。 感谢您的回答!

如果我的代码有其他问题,您有时间请告诉我!

提前致谢!

【问题讨论】:

    标签: c++ string pointers stl


    【解决方案1】:

    new char(*node_name) 分配与node_name 的第一个字符对应的单个字符。不是字符串。当您像使用 NULL 终止的 C 字符串一样使用它时,会丢失终止符字节,您会得到垃圾。

    char* 对于 std::cout 和其他流来说是特殊的,因为它表示“以空值结尾的 C 字符串”。您必须取消对它的引用 (&lt;&lt; *_node_name &lt;&lt;),或者像 hmjd 建议的那样,只需使用单个字符 (char node_name)。

    当您使用node_name 而不重新分配时,您将面临指针所指的空间在您需要时已经消失的风险。您不拥有指向的内存,因此您应该立即使用它或复制它。

    一般来说,编写自己的异常类并不容易,需要考虑的因素很多。在您的情况下,只需从 std::logic_errorstd::runtime_error 派生,并让它们处理字符串。

    【讨论】:

    • 这正是我想要的,每个节点上只有一个字符。
    • @Anton,然后使用char 而不是char*
    • @Anton:char* 对于 std::cout 和其他流来说是特殊的,因为它表示“以空值结尾的 C 字符串”。您必须取消引用它,或者像 hmjd 建议的那样,只需使用单个 char
    • 好的,谢谢!我想将其标记为答案,因为这是我的问题,我想知道当输入是指针时如何处理输入。您能否编辑它以包含在您的答案中?
    【解决方案2】:

    为什么要使用指针?你的节点名是单个char,这样对待。

    class NoSuchNode : public std::exception
    {
    private:
      char _node_name;
    public:
      NoSuchNode(char node_name) : _node_name(node_name) { }
      virtual const char* what() const throw()
        {
          std::stringstream ss;
          ss << "There exists no node for: " << _node_name << ".";
          const std::string& tmp = ss.str();
          return tmp.c_str();
        }
    };
    

    (我已将构造函数中的赋值替换为初始化。这是一般的最佳实践。)

    【讨论】:

      【解决方案3】:

      返回不是一个好主意 返回 tmp.c_str(); 因为 tmp.c_str() 返回一个指向内存位置的指针,该内存位置将在函数返回后被释放。

      【讨论】:

      • 哦,我不知道,我应该使用类似 char ret = *(tmp.c_str()); 的东西吗?
      猜你喜欢
      • 2021-07-28
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-26
      • 2023-03-17
      • 2021-11-26
      • 2012-10-04
      相关资源
      最近更新 更多