关于堆栈展开,c ++标准说:
在完成异常对象([except.throw])的初始化之后,异常被认为是未捕获的,直到完成异常处理程序的激活([except.handle]).这包括堆栈展开.
在标准杆15.5.3现行标准的.我试图理解最新的句子(This includes stack unwindings
)是指什么:
问题来自以下片段:
#include <iostream>
#include <exception>
struct S{
S() { std::cout << " S constructor" << std::endl; }
virtual ~S() { std::cout << " S destructor" << std::endl; }
};
void f() {
try{throw(0);}
catch(...){}
}
void g() {
throw(10);
}
int main() {
S s;
f();
//g();
}
Run Code Online (Sandbox Code Playgroud)
现在:
f();
和取消注释g();
(没有捕获异常),你有一堆堆栈没有被解开所以,这两个实验似乎赞成上面的第一个子弹; clang ++和g ++都同意结果(但它不是判别式).
此外,在我看来,非常奇怪的是标准,在指定对象的实时时间和持续时间时非常小心,这里留下了阴影.
愿有人澄清吗?堆栈是否为标准保证的未捕获异常展开?如果是的话,在哪里?如果没有,为什么?
标题已经是问题了.
更多细节:标准制定:
如果枚举键之后是嵌套名称说明符,则枚举说明符应引用先前在嵌套名称说明符所引用的类或命名空间中直接声明的枚举(即,既不继承也不引入通过using-declaration),enum-specifier应出现在包含前一个声明的命名空间中.
在7.2,第4段.例如,这禁止转发声明在类中定义的枚举:
struct S{
enum foo{A, B};
};
Run Code Online (Sandbox Code Playgroud)
现在,S
可以向前宣布,而S::foo
不是.
问题是为什么.是否存在这种规则可以带来好处的情况?为什么需要?或者,如果您愿意:如果标准没有此规则,是否存在编译器出现问题的情况?哪个)?
请考虑以下代码段:
#include <iostream>
template <int I>
constexpr int f() { return I * f<I-1>(); }
template<>
constexpr int f<0>() { return 1; }
int main () {
std::cout << f<5>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这段代码可以很好地编译g ++和clang.非常好.现在添加static
到模板函数专门化:
template<>
constexpr static int f<0>() { return 1; }
Run Code Online (Sandbox Code Playgroud)
然后g ++ 6.1对错误做出反应:
11:错误:显式模板专业化不能有存储类
和clang 3.8:
11:错误:显式特化具有无关的,不一致的存储类'静态'
他们看起来像是一致的.再好不过.现在,添加static
关键字也是模板功能的一般情况:
g ++ 6.1:
11:错误:显式模板专业化不能有存储类
clang 3.8编译并发出警告:
11:警告:显式专业化不能有存储类
和clang结果返回正确的答案.
这是clang中的错误吗?如果没有,在哪种情况下不抛出错误是有道理的?
c++ templates language-lawyer function-templates storage-class-specifier
关于CMake专家的一个问题.根据CMake 函数文档,函数根本不返回任何内容.要更改变量值,必须将其传递给函数,并在函数内部设置指定PARENT_SCOPE
选项的新值.很好,这是CMake的一个众所周知的功能.
我的问题不是关于如何,而是关于为什么:为什么CMake函数不返回值?背后的想法是什么?例如,函数不能在if
表达式中使用,也不能在set
命令内部调用.如果我没记错的话,它与autotools是一样的,因此我认为这不是偶然的.
有专家知道为什么吗?
请考虑以下代码段:
#include <iostream>
int main() {
int s[6] {0, 1, 2, 3, 4, 5};
for ( auto && i: s ) {
std::cout << " " << i << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
这在g ++和clang ++下编译和运行都很愉快.
它在许多帖子中被认为是理所当然的(例如这里和这里),但我不清楚编译器如何在for range
没有迭代器的情况下正确地推断出数组的大小.
任何人都可以回答或添加引用的链接吗?
我理解这对代码来说是愚蠢的...但为了理解,请考虑以下事项:
#include <iostream>
#include <memory>
#include <utility>
struct S;
void f( S && s );
struct S {
S() : i{std::vector<int>(10, 42)} {}
std::vector<int> i;
void call_f() { f( std::move(*this) ); }
void read() { std::cout << " from S: " << i.at(3) << std::endl; }
};
void f(S && s) { std::cout << " from f: " << s.i.at(3) << std::endl; }
int main() {
S s;
s.call_f();
s.read();
}
Run Code Online (Sandbox Code Playgroud)
这为g ++和clang ++编译和运行,而我希望它std::vector<int>
会被移动.在gdb中运行并查看内存显示,地址后s.i
未设置为零std::move
,而我预计非POD类型的地址.因此,我期望从这段代码中出现段错误. …
我对这个片段感到困惑:
constexpr int f(bool b) {
return b ? throw 0 : 0; }
constexpr int f() { return f(true); }
Run Code Online (Sandbox Code Playgroud)
直接来自c ++草案.我所强调的一点是,为什么标准将constexpr
没有参数的函数定义为格式错误(在同一链接中说明).愿有人澄清吗?