当前位置: 首页 > 编程日记 > 正文

C++/C++11中std::exception的使用

std::exception:标准异常类的基类,其类的声明在头文件<exception>中。所有标准库的异常类均继承于此类,因此通过引用类型可以捕获所有标准异常。

std::exception类定义了无参构造函数、拷贝构造函数、拷贝赋值运算符、一个虚析构函数和一个名为what的无参虚成员。其中what函数返回一个const char*,该指针指向一个以null结尾的字符数组,并且确保不会抛出任何异常,该字符串的目的是提供关于异常的一些文本信息。除析构函数外,其它函数均通过关键字noexcept说明此函数不会抛出异常。

std::exception is the class whose only purpose is to serve as the base class in the exception hierarchy. It has no other uses. In other words, conceptually it is an abstract class (even though it is not defined as abstract class in C++ meaning of the term).

以下内容摘自:《C++Primer(Fifth Edition)》

异常是指在程序运行时发生的反常行为,这些行为超出了函数正常功能的范围。典型的异常包括失去数据库连接以及遇到意外输入等。当程序的某部分检测到一个它无法处理的问题时,需要用到异常处理。此时,检测出问题的部分应该发出某种信号以表明程序遇到了故障,无法继续下去了,而且信号的发出方无须知道故障将在何处得到解决。一旦发出异常信号,检测出问题的部分也就完成了任务。

异常提供了一种转移程序控制权的方式。C++异常处理涉及到三个关键字:try、catch、throw。关于这三个关键字的简单使用可以参考: http://blog.csdn.net/fengbingchun/article/details/65939258

异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。在C++语言中,异常处理包括:

(1)、throw表达式(throw expression):异常检测部分使用throw表达式来表示它遇到了无法处理的问题。throw引发(raise)异常。throw表达式包含关键字throw和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型。throw表达式后面通常紧跟一个分号,从而构成一条表达式语句。抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码

(2)、try语句块(try block):异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句(catch clause)结束。try语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句处理异常,所以它们也被称作异常处理代码(exception handler)。catch子句包括三部分:关键字catch、括号内一个(可能未命名的)对象的声明(称作异常声明,exception declaration)以及一个块。当选中了某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。一如往常,try语句块声明的变量在块外部无法访问,特别是在catch子句内也无法访问。如果一段程序没有try语句块且发生了异常,系统会调用terminate函数并终止当前程序的执行。

(3)、一套异常类(exception class):用于在throw表达式和相关的catch子句之间传递异常的具体信息。

函数在寻找处理代码的过程中退出:寻找处理代码的过程与函数调用链刚好相反。当异常被抛出时,首先搜索抛出该异常的函数。如果没有找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。如果还是没有找到匹配的catch子句,这个新的函数也被终止,继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直到找到适当类型的catch子句为止。如果最终还是没能找到任何匹配的catch子句,程序转到名为terminate的标准库函数。该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。

如果一段程序没有try语句块且发生了异常,系统会调用terminate函数并终止当前程序的执行。

那些在异常发生期间正确执行了”清理”工作的程序被称作异常安全(exception safe)的代码。编写异常安全的代码非常困难。

标准异常:C++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类也可以在用户编写的程序中使用,它们分别定义在4个头文件中:

(1)、exception头文件定义了最通常的异常类std::exception,它只报告异常的发生,不提供任何额外的信息。

(2)、stdexcept头文件定义了几种常用的异常类,如下:

(3)、new头文件定义了bad_alloc异常类型。

(4)、type_info头文件定义了bad_cast异常类型。

标准库异常类只定义了几种运算,包括创建或拷贝异常类型的对象,以及为异常类型的对象赋值。我们只能以默认初始化的方式初始化exception、bad_alloc和bad_cast对象,不允许为这些对象提供初始值。其它异常类型的行为则恰恰相反:应该使用string对象或者C风格字符串初始化这些类型的对象,但是不允许使用默认初始化的方式。当创建此类对象时,必须提供初始值,该初始值含有错误相关的信息。

异常类型只定义了一个名为what的成员函数,该函数没有任何参数,返回值是一个指向C风格字符串的const char*。该字符串的目的是提供关于异常的一些文本信息。what函数返回的C风格字符串的内容与异常对象的类型有关。如果异常类型有一个字符串初始值,则what返回该字符串。对于其它无初始值的异常类型来说,what返回的内容由编译器决定。

异常处理(exception handling)机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理。异常使得我们能够将问题的检测与解决过程分离开来。程序的一部分负责检测问题的出现,然后解决该问题的任务传递给程序中的另一部分。检测环节无须知道问题处理模块的所有细节,反之亦然。

抛出异常:在C++语言中,我们通过抛出(throwing)一条表达式来引发(raised)一个异常。被抛出的表达式的类型以及当前的调用链共同决定了哪段处理代码(handler)将被用来处理该异常。被选中的处理代码是在调用链中与抛出对象类型匹配的最近的处理的代码。其中,根据抛出对象的类型和内容,程序的异常抛出部分将会告知异常处理部分到底发生了什么错误。

当执行一个throw时,跟在throw后面的语句将不再被执行,throw语句的用法有点类似于return语句:它通常作为调节语句的一部分或者作为某个函数的最后(或者唯一)一条语句。相反,程序的控制权从throw转移到与之匹配的catch模块。该catch可能是同一个函数中的局部catch,也可能位于直接或间接调用了发生异常的函数的另一个函数中。

当抛出一个异常后,程序暂停当前函数的执行过程并立即开始寻找与异常匹配的catch子句。当throw出现在一个try语句块内时,检查与该try块关联的catch子句。如果找到了匹配的catch,就使用该catch处理异常。如果这一步没找到匹配的catch且该try语句嵌套在其它try块中,则继续检查与外层try匹配的catch子句。如果还是找不到匹配的catch,则退出当前的函数,在调用当前函数的外层函数中继续寻找,依次类推。这一过程被称为栈展开(stack unwinding)过程。栈展开过程沿着嵌套函数的调用链不断查找,直到找到了与异常匹配的catch子句为止:或者也可能一直没找到匹配的catch,则退出主函数后查找过程终止。

假设找到了一个匹配的catch子句,则程序进入该子句并执行其中的代码。当执行完这个catch子句后,找到与try块关联的最后一个catch子句之后的点,并从这里继续执行。如果没找到匹配的catch子句,程序将退出。因为异常通常被认为是妨碍程序正常执行的事件,所以一旦引发了某个异常,就不能对它置之不理。当找不到匹配的catch时,程序将调用标准库函数terminate,terminate负责终止程序的执行过程。

Note:一个异常如果没有被捕获,则它将终止当前的程序

栈展开过程中对象被自动销毁:在栈展开过程中,位于调用链上的语句块可能会提前退出。通常情况下,程序在这些块中创建了一些局部对象。块退出后它的局部对象也将随之销毁,这条规则对于栈展开过程同样适用。如果在栈展开过程中退出了某个块,编译器将负责确保在这个块中创建的对象能被正确地销毁。如果某个局部对象的类型是类类型,则该对象的析构函数将被自动调用。与往常一样,编译器在销毁内置类型的对象时不需要做任何事情。

析构函数与异常:析构函数总是会被执行的。出于栈展开可能使用析构函数的考虑,析构函数不应该抛出不能被它自身处理的异常。换句话说,如果析构函数需要执行某个可能抛出异常的操作,则该操作应该被放置在一个try语句块当中,并且在析构函数内部得到处理。一旦在栈展开的过程中析构函数抛出了异常,并且析构函数自身没能捕获到异常,则程序将被终止。

异常对象(exception object):是一种特殊的对象,编译器使用异常抛出表达式来对异常对象进行拷贝初始化。因此,throw语句中的表达式必须拥有完全类型。而且如果该表达式是类类型的话,则相应的类必须含有一个可访问的析构函数和一个可访问的拷贝或移动构造函数。如果该表达式是数组类型或函数类型,则表达式将被转换成与之对应的指针类型。异常对象位于由编译器管理的空间中,编译器确保无论最终调用的是哪个catch子句都能访问该空间。当异常处理完毕后,异常对象被销毁。如果退出了某个块,则同时释放块中局部对象使用的内存。因此,抛出一个指向局部对象的指针几乎肯定是一种错误的行为。出于同样的原因,从函数中返回指向局部对象的指针也是错误的。当我们抛出一条表达式时,该表达式的静态编译时类型决定了异常对象的类型。如果一条throw表达式解引用一个基类指针,而该指针实际指向的是派生类对象,则抛出的对象将被切掉一部分,只有基类部分被抛出。

捕获异常:catch子句(catch clause)中的异常声明(exception declaration)看起来像是只包含一个形参的函数形参列表。像在形参列表中一样,如果catch无须访问抛出的表达式的话,则我们可以忽略捕获形参的名字。声明的类型决定了处理代码所能捕获的异常类型.这个类型必须是完全类型,它可以是左值引用,但不能是右值引用。

当进入一个catch语句后,通过异常对象初始化异常声明中的参数。和函数的参数类似,如果catch的参数类型是非引用类型,则该参数是异常对象的一个副本,在catch语句内改变参数实际上改变的是局部副本而非异常对象本身;相反,如果参数是引用类型,则和其它引用参数一样,该参数是异常对象的一个别名,此时改变参数也就是改变异常对象。

catch的参数还有一个特性也与函数的参数非常类似:如果catch的参数是基类类型,则我们可以使用其派生类类型的异常对象对其进行初始化。此时,如果catch的参数是非引用类型,则异常对象将被切掉一部分,这与将派生类对象以值传递的方式传给一个普通函数差不多。另一方面,如果catch的参数是基类的引用,则该参数将以常规方式绑定到异常对象上。

异常声明的静态类型将决定catch语句所能执行的操作。如果catch的参数是基类类型,则catch无法使用派生类特有的任何成员。

通常情况下,如果catch接受的异常与某个继承体系有关,则最好将该catch的参数定义成引用类型

查找匹配的处理代码:在搜索catch语句的过程中,我们最终找到的catch未必是异常的最佳匹配。相反,挑选出来的应该是第一个与异常匹配的catch语句。因此,越是专门的catch越应该置于整个catch列表的前端。因为catch语句是按照其出现的顺序逐一进行匹配的,所以当程序使用具有继承关系的多个异常时必须对catch语句的顺序进行组织和管理,使得派生类异常的处理代码出现在基类异常的处理代码之前。

与实参和形参的匹配规则相比,异常和catch异常声明的匹配规则受到更多限制。此时,绝大多数类型转换都不被允许,除了一些极细小的差别之外,要求异常的类型和catch声明的类型是精确匹配的:

(1)、允许在非常量向常量的类型转换,也就是说,一条非常量对象的throw语句可以匹配一个接受常量引用的catch语句。

(2)、允许从派生类向基类的类型转换。

(3)、数组被转换成指向数组(元素)类型的指针,函数被转换成指向该函数类型的指针。

除此之外,包括标准算术类型转换和类类型转换在内,其它所有转换规则都不能在匹配catch的过程中使用。

如果在多个catch语句的类型之间存在着继承关系,则我们应该把继承链最低端的类(most derived type)放在前面,而将继承链最顶端的类(least derived type)放在后面

重新抛出:有时,一个单独的catch语句不能完整地处理某个异常。在执行了某些校正操作之后,当前的catch可能会决定由调用链更上一层的函数接着处理异常。一条catch语句通过重新抛出(rethrowing)的操作将异常传递给另外一个catch语句。这里的重新抛出仍然是一条throw语句,只不过不包含任何表达式:throw;

空的throw语句只能出现在catch语句或catch语句直接或间接调用的函数之内。如果在处理代码之外的区域遇到了空throw语句,编译器将调用terminate。

一个重新抛出语句并不指定新的表达式,而是将当前的异常对象沿着调用链向上传递。

很多时候,catch语句会改变其参数的内容。如果在改变了参数的内容后catch语句重新抛出异常,则只有当catch异常声明是引用类型时我们对参数所做的改变才会被保留并继续传播。

捕获所有异常的处理代码:为了一次性捕获所有异常,我们使用省略号作为异常声明,这样的处理代码称为捕获所有异常(catch-all)的处理代码,形如catch(…)。一条捕获所有异常的语句可以与任意类型的异常匹配。

catch(…)通常与重新抛出语句一起使用,其中catch执行当前局部能完成的工作,随后重新抛出异常。

catch(…)既能单独出现,也能与其它几个catch语句一起出现。

如果catch(…)与其它几个catch语句一起出现,则catch(…)必须在最后的位置。出现在捕获所有异常语句后面的catch语句将永远不会被匹配

函数try语句块与构造函数:通常情况下,程序执行的任何时刻都可能发生异常,特别是异常可能发生在处理构造函数初始值的过程中。构造函数在进入其函数体之前首先执行初始值列表。因为在初始值列表抛出异常时构造函数体内的try语句块还未生效,所以构造函数体内的catch语句无法处理构造函数初始值列表抛出的异常。要想处理构造函数初始值抛出的异常,我们必须将构造函数写出函数try语句块(也称为函数测试块,function try block)的形式。函数try语句块使得一组catch语句既能处理构造函数体(或析构函数体),也能处理构造函数的初始化过程(或析构函数的析构过程)。

在初始化构造函数的参数时也可能发生异常,这样的异常不属于函数try语句块的一部分。函数try语句块只能处理构造函数开始执行后发生的异常。和其它函数调用一样,如果在参数初始化的过程中发生了异常,则该异常属于调用表达式的一部分,并将在调用者所在的上下文中处理。

处理构造函数初始值异常的唯一方法是将构造函数写成函数try语句块

noexcept异常说明:在C++11新标准中,我们可以通过提供noexcept说明(noexcept specification)指定某个函数不会抛出异常。其形式是关键字noexcept紧跟在函数的参数列表后面,用以标识该函数不会抛出异常。

对于一个函数来说,noexcept说明要么出现在该函数的所有声明语句和定义语句中,要么一次也不出现。该说明应该在函数的尾置返回类型之前。我们也可以在函数指针的声明和定义中指定noexcept。在typedef或类型别名中则不能出现noexcept。在成员函数中,noexcept说明符需要跟在const及引用限定符之后,而在final、override或虚函数的=0之前。

违反异常说明:如果一个函数在说明了noexcept的同时又含有throw语句或者调用了可能抛出异常的其它函数,编译器将顺利编译通过,并不会因为这种违反异常说明的情况而报错(不排除个别编译器会对这种用法提出警告)。一旦一个noexcept函数抛出了异常,程序就会调用terminate以确保遵守不在运行时抛出异常的承诺。noexcept可以用在两种情况下,一是我们确认函数不会抛出异常;二是我们根本不知道该如何处理异常。

通常情况下,编译器不能也不必在编译时验证异常说明。

如果函数被设计为是throw()的,则意味着该函数将不会抛出异常:void f(int) throw();

异常说明的实参:noexcept说明符接受一个可选的实参,该实参必须能转换为bool类型:如果实参是true,则函数不会抛出异常;如果实参是false,则函数可能抛出异常。

noexcept运算符:noexcept说明符的实参常常与noexcept运算符(noexcept orerator)混合使用。noexcept运算符是一个一元运算符,它的返回值是一个bool类型的右值常量表达式,用于表示给定的表达式是否会抛出异常。和sizeof类似,noexcept也不会求其运算对象的值。

noexcept有两层含义:当跟在函数参数列表后面时它是异常说明符;而当作为noexcept异常说明的bool实参出现时,它是一个运算符

异常说明与指针、虚函数和拷贝控制:尽管noexcept说明符不属于函数类型的一部分,但是函数的异常说明仍然会影响函数的使用。函数指针及该指针所指的函数必须具有一致的异常说明。也就是说,如果我们为某个指针做了不抛出异常的说明,则该指针将只能指向不抛出异常的函数。相反,如果我们显示或隐式地说明了指针可能抛出异常,则该指针可以指向任何函数,即使是承诺了不抛出异常的函数也可以。

如果一个虚函数承诺了它不会抛出异常,则后续派生出来的虚函数也必须做出同样的承诺;与之相反,如果基类的虚函数允许抛出异常,则派生类的对应函数既可以允许抛出异常,也可以不允许抛出异常。

当编译器合成拷贝控制成员时,同时也生成一个异常说明。如果对所有成员和基类的所有操作都承诺了不会抛出异常,则合成的成员是noexcept的。如果合成成员调用的任意一个函数可能抛出异常,则合成的成员是noexcept(false)。而且,如果我们定义了一个析构函数但是没有为它提供异常说明,则编译器将合成一个。合成的异常说明将与假设由编译器为类合成析构函数时所得的异常说明一致。

异常类层次:标准库异常类构成了下图所示的继承体系:

类型exception仅仅定义了拷贝构造函数、拷贝赋值运算符、一个虚析构函数和一个名为what的虚成员。其中what函数返回一个const char*,该指针指向一个以null结尾的字符数组,并且确保不会抛出任何异常。

类exception、bad_cast和bad_alloc定义了默认构造函数。类runtime_error和logic_error没有默认构造函数,但是有一个可以接受C风格字符串或者标准库string类型实参的构造函数,这些实参负责提供关于错误的更多信息。在这些类中,what负责返回用于初始化异常对象的信息。因为what是虚函数,所以当我们捕获基类的引用时,对what函数的调用将执行与异常对象动态类型对应的版本。

实际的应用程序通常会自定义exception(或者exception的标准库派生类)的派生类以扩展其继承体系。这些面向应用的异常类表示了与应用相关的异常条件。和其它继承体系一样,异常类也可以看作按照层次关系组织的。层次越低,表示的异常情况就越特殊。例如,在异常类继承体系中位于最顶层的通常是exception,exception表示的含义是某处出错了,至于错误的细节则未作描述。

继承体系的第二层将exception划分为两个大的类别:运行时错误和逻辑错误。运行时错误表示的是只有在程序运行时才能检测到的错误;而逻辑错误一般指的是我们可以在程序代码中发现的错误。

下面是从其他文章中copy的std::exception测试代码,详细内容介绍可以参考对应的reference:

#include "exception.hpp"
#include <exception>
#include <typeinfo>
#include <iostream>
#include <utility>
#include <cstring>// Fix: error C3646: 'noexcept' : unknown override specifier
#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endifnamespace exception_ {
/
// reference: http://www.cplusplus.com/reference/exception/exception/
class Polymorphic { virtual void member(){}
};int test_exception_1()
{try {Polymorphic * pb = 0;typeid(*pb); // throws a bad_typeid exception} catch (std::exception& e) { // std::std::bad_typeidstd::cerr << "exception caught: " << e.what() << '\n'; // exception caught: Attempted a typeid of Null pointer!}return 0;
}struct ooops : std::exception {const char* what()  const NOEXCEPT /*noexcept*/ override{ return "Ooops!\n"; }
};int test_exception_2()
{ooops e;std::exception* p = &e;try {throw e;       // throwing copy-constructs: ooops(e)} catch (std::exception& ex) {std::cout << ex.what(); // 0oops!}try {throw *p;      // throwing copy-constructs: std::exception(*p)} catch (std::exception& ex) {std::cout << ex.what(); // Unknown exception}return 0;
}// text_exception uses a dynamically-allocated internal c-string for what():
class text_exception : public std::exception {
public:text_exception(const char* text) {text_ = new char[std::strlen(text) + 1];std::strcpy(text_, text);}text_exception(const text_exception& e) {text_ = new char[std::strlen(e.text_) + 1];std::strcpy(text_, e.text_);}~text_exception() NOEXCEPT /*throw()*/ {delete[] text_;}const char* what() const NOEXCEPT /*noexcept*/ override { return text_; }private:char* text_;
};int test_exception_3()
{try {throw text_exception("custom text\n");} catch (std::exception& ex) {std::cout << ex.what(); // custom text}return 0;
}} // namespace exception_

GitHub: https://github.com/fengbingchun/Messy_Test

相关文章:

技术不错的程序员,为何面试却“屡战屡败”

为何很多有不少编程经验&#xff0c;技术能力不错的程序员&#xff0c;去心仪公司面试时却总是失败&#xff1f;至于失败的原因&#xff0c;可能很多人都没意识到过。01想要通关面试&#xff0c;千万别让数据结构拖了后腿很多公司&#xff0c;比如 BAT、Google、Facebook&#…

FastJson 转换 javaBean 时 null 值被忽略都问题

[toc] 问题 当 JavaeBean 中某个属性值为 null 时&#xff0c;转换为 JSONObject 对象或者 json 字符串时&#xff0c;该属性值被忽略。如何让不管值是否为 null&#xff0c;转化后该属性还存在&#xff0c;只是值为 null。 情况演示 class St {private String sid;private Str…

来玩Play框架07 静态文件

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01; Play框架的主要功能是提供动态响应的内容。但一个网络项目中必然有大量的静态内容&#xff0c;比如图片、Javascript文件、CSS文件等。我下面介绍…

C++/C++11中std::runtime_error的使用

std::runtime_error&#xff1a;运行时错误异常类&#xff0c;只有在运行时才能检测到的错误&#xff0c;继承于std::exception&#xff0c;它的声明在头文件<stdexcept>中。std::runtime_error也用作几个运行时错误异常的基类&#xff0c;包括std::range_error(生成的结…

估值被砍700亿美元后,Waymo发重磅公开信:即将推出全自动驾驶打车服务

&#xff08;图片源自 Waymo 官网&#xff09;编译 | 夕颜出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;近日&#xff0c;据 Reddit 盛传的一封电子邮件副本显示&#xff0c;Alphabet 旗下的自动驾驶汽车公司 Waymo 已经向其自动驾驶服务的用户发送了一封电子邮件&…

Swoft 2 Beta 发布,基于 Swoole 的云原生协程框架

Swoft 是首个基于 Swoole 原生协程的框架&#xff0c;从开发到发布据今已有2年多。 1.x 发布以来&#xff0c;已有大量的开发人员和企业使用&#xff0c;得到了大家的认可。从去年11月份开始&#xff0c;将近半年的时间从零开始&#xff0c;底层吸取之前经验&#xff0c;基于 S…

Linux中源码包的管理

什么是开放源码&#xff0c;编译程序和可执行文件开放源码&#xff1a;就是程序代码,写给人类看的程序语言,但机器不认识,所以无法执行&#xff1b;编译程序&#xff1a;将程序代码转译成为机器看得懂的语言&#xff1b;可执行文件&#xff1a;经过编译程序变成二进制程序后,机…

支持向量机(SVM)简介

支持向量机(support vector machine, SVM)&#xff1a;是监督学习中最有影响力的方法之一。类似于逻辑回归&#xff0c;这个模型也是基于线性函数wTxb的。不同于逻辑回归的是&#xff0c;支持向量机不输出概率&#xff0c;只输出类别。当wTxb为正时&#xff0c;支持向量机预测属…

首届中文NL2SQL挑战赛:千支队伍参赛,国防科大夺冠

&#xff08;图片由AI科技大本营付费下载自视觉中国&#xff09;整理 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;【导语】10月12日&#xff0c;追一科技主办的首届中文NL2SQL挑战赛在激烈的决赛中落下帷幕&#xff0c;冠军由国防科技大学学生组…

怎么使用CAD编辑器来打开图纸中的所有图层

在CAD绘图中&#xff0c;建筑设计师们不仅要对CAD图纸进行编辑&#xff0c;还要对CAD图纸进行查看&#xff0c;一张图纸中是有许多图层的&#xff0c;那在查看的过程中有的时候把其他的图层进行隐藏了&#xff0c;那如果想要把隐藏的CAD图层进行打开要怎么操作&#xff1f;如何…

域名年龄-SEO搜索引擎优化

为什么80%的码农都做不了架构师&#xff1f;>>> 域名年龄-SEO搜索引擎优化 在我们创建一个新的网站时&#xff0c;我们首先考虑到的是去注册一个新的域名。 有时发现我们 要注册的域名已经被注册了&#xff0c;于是就有两种方式&#xff1a; 一、重新注册另外的…

log库spdlog简介及使用

spdlog是一个开源的、快速的、仅有头文件的C11 日志库&#xff0c;code地址在 https://github.com/gabime/spdlog &#xff0c;目前最新的发布版本为0.14.0。它提供了向流、标准输出、文件、系统日志、调试器等目标输出日志的能力。它支持的平台包括Windows、Linux、Mac、Andro…

多模态人物识别技术及其在视频场景中的应用 | CSDN技术公开课

不用倍速播放&#xff0c;还有什么功能可以让你高效追剧&#xff1f;爱奇艺的「只看TA」了解一下&#xff1f;而这个功能背后离不开多模态人物识别技术的支撑。识别视频中的人物涉及哪些信息&#xff1f;只有人脸识别就足够了吗&#xff1f;其实不然&#xff0c;这样一个看似简…

研究人员测试27个黑客服务 结果仅三个完成任务

现代电子邮件帐户不仅是一个电子邮件地址&#xff0c;它还是人们在网络上的身份的基础&#xff0c;可用于申请各种网络服务或重置服务密码&#xff0c;以便持有电子邮件的黑客服务帐户很受欢迎&#xff0c;为了了解这些服务的功能&#xff0c;谷歌和加州大学圣地亚哥分校的研究…

CIF、QCIF

分辨率&#xff1a; 每个像素的存储方式都是YUV QQCIF:88*72 QCIF:176*144 CIF:352*288 2CIF:704*288 DCIF:584*384 4CIF:704*576 QCIF&#xff1a; QCIF: Quarter Common Intermediate Format 英文缩写 qcif 英文全称 Quarter Common Intermediate Format 中文解释 四分之一通…

OpenCV3.3中支持向量机(Support Vector Machines, SVM)实现简介及使用

OpenCV 3.3中给出了支持向量机(Support Vector Machines)的实现&#xff0c;即cv::ml::SVM类&#xff0c;此类的声明在include/opencv2/ml.hpp文件中&#xff0c;实现在modules/ml/src/svm.cpp文件中&#xff0c;它既支持两分类&#xff0c;也支持多分类&#xff0c;还支持回归…

Facebook发布Detectron2,下一个万星目标检测新框架

作者 | CV君来源 | 我爱计算机视觉&#xff08;ID&#xff1a;aicvml&#xff09;Detectron是Facebook于2018年发布的专注于目标检测的深度学习框架&#xff0c;基于Caffe2深度学习框架&#xff0c;实现了众多state-of-the-art算法&#xff0c;其与商汤-香港中文大学MMLab实验室…

include和require的区别

细节决定成败&#xff01; 1.引用文件方式 对include()来说&#xff0c;在include()执行时文件每次都要进行读取和评估&#xff1b;而对于require()来说&#xff0c;文件只处理一次&#xff08;实际上&#xff0c;文件内容替换了require()语句&#xff09;。这就意味着如果有包…

libsvm库简介及使用

libsvm是基于支持向量机(support vector machine, SVM)实现的开源库&#xff0c;由台湾大学林智仁(Chih-Jen Lin)教授等开发&#xff0c;它主要用于分类(支持二分类和多分类)和回归。它的License是BSD-3-Clause&#xff0c;最新发布版本是v322。libsvm具有操作简单、易于使用、…

Cron 表达式极速参考

Cron表达式&#xff1a; * * * * * * *这些星号由左到右按顺序代表 &#xff1a; [秒] [分] [小时] [日] [月] [周] [年] 序号说明 是否必填 允许填写的值 允许的通配符1 秒 是 0-59 , - * /2 分 是 0-59…

刘群:华为诺亚方舟NLP预训练模型工作的研究与应用 | AI ProCon 2019

演讲嘉宾 | 刘群&#xff08;华为诺亚方舟实验首席科学家&#xff09;编辑 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;预训练语言模型对自然语言处理领域产生了非常大的影响&#xff0c;在近期由CSDN主办的 AI ProCon 2019 上&#xff0c;自然…

NuGet 无法连接到远程服务器-解决方法

一、 Entity Framework以下简称EF 安装EF4.3的步骤是首先安装VS扩展 NuGet&#xff0c;然后再使用NuGet安装EF程序包 安装完NuGet就可以安装EF了&#xff0c;有两种方式可以安装EF&#xff1a; 1.使用命令 install-package EntityFramework -Pre 但出现如下错误: 2.使用可视化工…

Facebook开源模型可解释库Captum,这次改模型有依据了

作者 | Narine Kokhlikyan, Vivek Miglani, Edward Wang, Orion Reblitz-Richardson译者 | Rachel出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;【导读】前脚 TF 2.0 刚发布&#xff0c;在 PyTorch 开发者大会首日也携 PyTorch1.3 版本而来。除此之外&a…

K-最近邻法(KNN)简介

K-最近邻法(K-Nearest Neighbor, KNN)最初由Cover和Hart于1968年提出&#xff0c;是一个在理论上比较成熟的分类算法。KNN是一类可用于分类或回归的技术。作为一个非参数学习算法&#xff0c;K-最近邻并不局限于固定数目的参数。我们通常认为K-最近邻算法没有任何参数&#xff…

demo17 clean-webpack-plugin (清除模式)

1.为什么需要自动清除 dist 文件夹 在之前的 demo 中&#xff0c;webpack 打包后会在根目录下自动创建 dist 目录&#xff0c;并且把生成的文件输出到 dist 下。 当配置的输出包名含有 [hash] 时&#xff0c;hash值会随着文件内容的改变而改变。 因此&#xff0c;我们需要在下一…

c语言-01背包问题

01背包问题 问题&#xff1a;有N件物品和一个容量为V的背包。第i件物品的费用是c[i]&#xff0c;价值是w[i]。求解将哪些物品装入背包可使价值总和最大。 分析&#xff1a; 这是最基础的背包问题&#xff0c;特点是&#xff1a;每种物品仅有一件&#xff0c;可以选择放或不放。…

OpenCV3.3中 K-最近邻法(KNN)接口简介及使用

OpenCV 3.3中给出了K-最近邻(KNN)算法的实现&#xff0c;即cv::ml::Knearest类&#xff0c;此类的声明在include/opecv2/ml.hpp文件中&#xff0c;实现在modules/ml/src/knearest.cpp文件中。其中&#xff1a;(1)、cv::ml::Knearest类&#xff1a;继承自cv::ml::StateModel&…

华为于璠:新一代AI开源计算框架MindSpore的前世与今生 | AI ProCon 2019

演讲嘉宾 | 于璠&#xff08;华为MindSpore资深架构师&#xff09;编辑 | 刘静出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;9月&#xff0c;2019中国AI开发者大会&#xff08;AI ProCon 2019&#xff09;在北京举行。在AI开源技术专题中&#xff0c;华为MindSpore…

TCC分布式事务的实现原理

目录 一、写在前面 二、业务场景介绍 三、进一步思考 四、落地实现TCC分布式事务 (1)TCC实现阶段一&#xff1a;Try (2)TCC实现阶段二&#xff1a;Confirm (3)TCC实现阶段三&#xff1a;Cancel 五、总结与思考 一、写在前面 之前网上看到很多写分布式事务的文章&#xff0c;不过…

Brute Force算法介绍及C++实现

字符串的模式匹配操作可以通过Brute Force算法来实现。字符串匹配操作即是查看S串(目标串或主串)中是否含有T串(模式串或子串)&#xff0c;如果在主串中查找到了子串&#xff0c;则模式匹配成功&#xff0c;返回模式串中的第一个字符在主串中的位置&#xff1b;如果未找到&…