我一直在使用Howard Hinnant的堆栈分配器,它就像一个魅力,但实现的一些细节对我来说有点不清楚.
new和delete使用?的allocate()和deallocate()成员函数使用::operator new和::operator delete分别.同样,成员函数construct()使用全局布局new.为什么不允许任何用户定义的全局或类特定的重载?std::alignment_of<T>?max_size有throw()异常规范?这不是劝阻(参见例如更有效的C++第14项)?在分配器中发生异常时,是否真的有必要终止和中止?这是否随新的C++ 11 noexcept关键字而改变?construct()成员函数将是完美转发(在构造函数被调用)的理想选择.这是编写符合C++ 11标准的分配器的方法吗?c++ memory-alignment exception-specification allocator c++11
std::exception要求它的构造函数是throw().然而std::runtime_error接受一个std::string作为它的论据,这表明它存储在std::string某个地方.因此,必须在某处进行分配或复制构造.而且std::string,这不是一项nothrow行动.
怎么会runtime_error::runtime_error遇到throw()?
(对于上下文,我正在实现一个异常类型,并希望std::string从调用站点存储几个,我想要正确地执行它...)
我知道这个功能将在C++ 0x中弃用,但对我来说,作为一个新手,拥有它似乎是一个好主意.任何人都可以向我解释为什么不是一个好主意?
C++标准声明了以下关于具有异常规范的虚函数:
如果虚函数具有异常规范,则任何在任何派生类中覆盖该虚函数的函数的所有声明(包括定义)都只允许基类虚函数的异常规范所允许的异常(C +) +03§15.4/ 3).
因此,以下是不正确的:
struct B {
virtual void f() throw() { } // allows no exceptions
};
struct D : B {
virtual void f() { } // allows all exceptions
};
Run Code Online (Sandbox Code Playgroud)
(1)此规则是否适用于析构函数?也就是说,以下是否良好?
struct B {
virtual ~B() throw() { }
};
struct D : B {
virtual ~D() { }
};
Run Code Online (Sandbox Code Playgroud)
(2)此规则如何应用于隐式声明的析构函数?也就是说,以下是否良好?
struct B {
virtual ~B() throw() { }
};
struct D : B {
// ~D() implicitly declared …Run Code Online (Sandbox Code Playgroud) c++ destructor exception-handling exception exception-specification
我正在尝试使用新的GCC版本7.2.1编译我的项目,并且遇到动态异常规范的问题:
error: ISO C++1z does not allow dynamic exception specifications
MEMORY_ALLOC_OPERATORS(SQLException)
Run Code Online (Sandbox Code Playgroud)
问题是这些错误来自我无法控制的第三方库.
有没有办法解决它?据我所知,我不能告诉编译器用警告替换错误.使用--std=c++14不是一个选项,因为我想使用C++ 1z的新功能.
在C++ 11中,隐式声明了没有任何异常规范的析构函数 noexcept,这是对C++ 03的更改.因此,用于从C++ 03中的析构函数抛出的代码仍然可以在C++ 11中正常编译,但是一旦尝试从这样的析构函数抛出就会在运行时崩溃.
由于这样的代码没有编译时错误,如何将它安全地转换为C++ 11,而不是将代码库中的所有现有析构函数声明为noexcept(false),这实际上是过于冗长和干扰,或者检查每个析构函数是否有可能抛出,这将非常耗时且容易出错,或者在运行时捕获并修复所有崩溃,这永远无法保证找到所有这些情况?
c++ destructor exception-handling exception-specification c++11
我在使用C++代码时遇到了问题,这些代码意外地对调用者抛出异常.读取用于查看是否抛出异常的模块的每一行并不总是可行或实际的,如果是,则抛出异常类型.
是否存在处理此问题的成语或"最佳实践"?
我想到了以下几点:
在我们的doxygen文档中,我们可以在每个预期会抛出异常及其类型的函数中添加注释.
我们可以安装应用程序try/catch(...).
使用例外规范
有这些方法的经验,还是我不知道的任何其他方法?
考虑这两个可能的类定义:
图表A:
struct A
{
A() = delete;
};
Run Code Online (Sandbox Code Playgroud)
图表A':
struct A
{
A() noexcept = delete;
}
Run Code Online (Sandbox Code Playgroud)
声明删除的函数是否有任何意义noexcept?
我有一个异常类如下:
#include <exception>
struct InvalidPathException : public std::exception
{
explicit InvalidPathException() {}
const char* what() const;
};
const char*
InvalidPathException::what() const {
return "Path is not valid";
}
Run Code Online (Sandbox Code Playgroud)
使用-Wall -std = c ++ 0x在GCC 4.4下编译时
错误:对'virtual const char*的错误抛出说明符*InvalidPathException :: what()const'
错误:覆盖'virtual const char*std :: exception :: what()const throw()'
完全正确,也因为我重写std::exception的what()是确实有一个方法throw()异常说明.但是,通常会通知我们,我们不应该使用异常说明符.据我所知,它们在C++ 11中已被弃用,但显然还没有在GCC中使用-std = c ++ 0x.
所以我现在对最好的方法感兴趣.在我正在开发的代码中,我确实关心性能,所以担心经常提到的开销throw(),但实际上这个开销是如此严重?我是否正确地认为我只会在what()实际调用时遇到它,这只会在抛出这样的异常之后(同样对于从std :: exception继承的其他方法都有throw()说明符)?
或者,有没有办法解决GCC给出的这个错误?
假设我有:
class Foo
{
public:
virtual ~Foo()=default;
};
Run Code Online (Sandbox Code Playgroud)
默认析构函数的异常规范是什么?违约的析构函数是否相当于:
virtual ~Foo() {};
or
virtual ~Foo() throw() {};
or
virtual ~Foo() noexcept {};
Run Code Online (Sandbox Code Playgroud)
C++ 11标准的第15.4节说它依赖于析构函数的隐式定义直接调用的函数的异常规范.在这种情况下,没有成员,也没有基类,因此AFAIK没有隐式析构函数直接调用的函数.这是标准中的含糊不清(或遗漏)吗?
当然,这很重要,因为如果它隐式具有throw(),那么所有子类必须使用throw()声明它们的析构函数.不要告诉我在析构函数中抛出异常是个坏主意,我知道.我处理了许多遗留代码,其中根本没有使用异常规范.
作为一个信息点,当我尝试时:
class SubFoo : public Foo
{
public:
virtual ~SubFoo();
};
Run Code Online (Sandbox Code Playgroud)
我在GCC 4.4中得到了一个错误(不匹配的异常规范)(尽管我承认我可能没有正确的命令行开关),但在使用"11"编译器的XCode 4.3中却没有.