g++ 与 MSVC 中 C++ 引号的含义

Posted

技术标签:

【中文标题】g++ 与 MSVC 中 C++ 引号的含义【英文标题】:The Meaning of C++ Quotes in g++ vs. MSVC 【发布时间】:2011-10-28 12:00:32 【问题描述】:

可能有一个谷歌搜索可以回答这个问题,但在我的一生中,我想不出一个能得到数百万个不相关的答案。

所以,

我认为,在 MSVC 中,引号内的“like this”文本被用作 std::string 或 std::string&。在 g++/gcc 中,它似乎总是被视为 const char*。是吗?

我找到了一个我想玩的代码 sn-p,它包含

if(NULL == key)
   throw exception("Empty key");

在 MSVC/VC++(2008) 中编译得很好(但是当我在 g++ (4.4.3) 上尝试时,我得到了

no matching functions for calls to std::exception::exception(const char&) 

我得到了这个工作:

if (NULL == key)

   std::string   estr   ("Empty key");
   throw exception("Empty key");

但这实在是太丑了。

这给我带来了不同的错误:

std::string   estr   ("");
if (NULL == key)

   estr = "Empty key";
   throw exception("Empty key");

我不知道 exception() 期望它的输入是什么。我确实找到了一些暗示 std::string 或 std::string& 的东西,但我丢失了那个页面,我发现的数百万无用的页面,嗯,没用。有关于异常类、异常使用等的各种信息......

除了我的丑陋修复之外,有没有一种简单的方法可以告诉 g++“这是一个 std::string”而不是 const char& 并且仍然让 VC++ 满意? (显然我正在尝试从单一来源做交叉编译代码。)

关于那件事,如何识别

   throw exception("Empty key");

不同于

   throw "Empty key";

谢谢,

韦斯

【问题讨论】:

抛出异常(new std::string("Empty key")); @DrewBurcett:exception 没有非默认构造函数,因此即使创建内存泄漏是个好主意(它不是),这也不起作用。 @MikeSeymour:好吧,也许我误会了。编译器是否没有告诉他异常需要 std::string?如果是这种情况,您将如何抛出一个传入 std::string 的异常,该异常将被销毁,因为控制权将永远不会传递回异常之外的任何点? @DrewBurcett:错误是说没有匹配的构造函数,并且没有说明预期的内容。 exception 的标准子类(例如 runtime_error)存储了用于初始化它们的字符串的副本,该副本与异常对象本身一样长。 【参考方案1】:

字符串文字总是具有char 数组的类型,其大小刚好足以包含带有空终止符的文字中的字符。所以"Empty key" 的类型为char[10]。如果需要,可以将其隐式转换为 char const *std::string

错误是因为exception 旨在作为异常类型的基类,而不是您直接实例化的东西。您应该抛出<stdexcept> 中定义的类型之一,例如std::runtime_error(可以使用字符串构造),或者定义您自己的继承std::exception 并覆盖what() 的类型。

我猜微软已经为std::exception 添加了一个非标准的构造函数。他们喜欢以奇怪的方式扩展语言。

【讨论】:

微软添加非标准构造函数是完全合法的,特别是因为它旨在用作标准库中其他异常的基类型。由于它们是标准库实现的一部分,因此这些其他异常可能会使用其基类的特定于实现的方法。使用特定于实现的基类甚至很常见。 @MSalters:当然这是合法的,我敢肯定,如果他们愿意,有人可以提出合理的理由将其公开。从可移植性的角度来看,这只是一个坏主意(正如这个问题所证明的那样)。 很好的答案!非常感谢。 看起来 g++ 也有一个用于std::exception 的非标准构造函数。否则,问题中的第二个示例将无法编译。 @Gorpik:看起来像 OP 使用的旧版本(假设发布的代码确实编译了,并且没有另一种称为 exception 隐藏 std::exception 的类型);更新的版本,至少从 4.4.5 开始,不要。【参考方案2】:

std::exception 是基类。

尝试抛出 std::runtime_error 。

【讨论】:

【参考方案3】:

避免通过类型std::string 引发异常,因为它们本身可以引发异常。如果发生这种情况,您最终会得到未定义的行为

抛出<stdexcept>中定义的标准异常,或者让你自己的异常类派生自std::exception类并抛出它。并重写what()方法以添加适当的异常描述。

此外,始终按值 throw 和按引用 catch

【讨论】:

【参考方案4】:

根据标准,"like this" 始终被视为const char 的数组。这不是这里的问题。真正发生的是 std::exception 只有默认构造函数,再次根据标准。通常会包含一个采用文本字符串的附加构造函数,但如您的示例所示,此构造函数在 VC++ 和 g++ 中的工作方式不同。

我在这里没有 g++ 文档,但是从您的示例中,它看起来像是将非标准构造函数定义为:

explicit exception(const std::string&);

而 VC++ 将非标准构造函数定义为:

explicit exception(const char*);

【讨论】:

以上是关于g++ 与 MSVC 中 C++ 引号的含义的主要内容,如果未能解决你的问题,请参考以下文章

Shell 基础 -- 总结几种括号引号的用法

bash中的引用

关于反引号和 %string 含义的问题 [重复]

C++中String类find函数与string::npos的含义

C++ 版本,它们的含义,如何更新它们

python爬虫:解决请求路径中含义中文或特殊字符