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++ 引号的含义的主要内容,如果未能解决你的问题,请参考以下文章