我偶然注意到了以下行为(通过引用错过了捕获),但我找不到如果我事先知道的话,可以让我预测它的信息。
用最小的例子
#include <iostream>
#include <stdexcept>
int main()
{
try
{
// Added this and the next line to check that the exception
// created has already the what() set to the input string.
std::out_of_range d("Out of range exception");
std::cout << "d.what() = " << d.what() << std::endl;
throw d;
}
catch (std::exception e) // Captured by value
{
std::cout << e.what() << std::endl;
}
}
如果我g++ -std=c++17
用 Visual C++ 编译它,我会得到不同的行为。第一个打印d.what() = Out of range exception\nstd::exception
,第二个打印d.what() = Out of range exception\nOut of range exception
。
std::out_of_range
原则上,当按值捕获并转换为std::exception
类型时,可能会有切片。这意味着我可以期望std::out_of_range
在打印对象时不会得到与对象相同的行为what()
。
问题:我不知道如何解释的部分是两个编译器的不同行为。这是因为这种切片在 C++ 标准化中是未定义的行为,还是这两个编译器之一不符合它?
额外的观察:我只是注意到在这个链接中没有提到这个类std::exception
有一个输入 a 的构造函数const char* const &
,而在微软网站上它们包括它。我偶然的例子表明他们确实以不同的方式实现了这些类。我的问题仍然是他们是否被允许(如果这种行为是未定义的),或者他们中的一个不遵守,哪一个。