当前位置: 首页 > news >正文

类似wordpress的建站系统网站排名下降原因

类似wordpress的建站系统,网站排名下降原因,鄂尔多斯市建设网站,wordpress上传图片自动压缩目录 0.前言 1.C语言传统错误处理方式 1.1使用返回值 1.2使用全局变量 1.3使用断言 1.4优缺点 2.C异常的概念 3.异常的使用 3.1异常的抛出和捕获 3.1.1异常的抛出和匹配原则 3.1.2在函数调用链中异常栈展开匹配原则 3.2异常的重新抛出 3.3异常安全 3.4异常规范 4.自定义异常体系… 目录 0.前言 1.C语言传统错误处理方式 1.1使用返回值 1.2使用全局变量 1.3使用断言 1.4优缺点 2.C异常的概念 3.异常的使用 3.1异常的抛出和捕获 3.1.1异常的抛出和匹配原则 3.1.2在函数调用链中异常栈展开匹配原则 3.2异常的重新抛出 3.3异常安全 3.4异常规范 4.自定义异常体系 5.C标准库的异常体系 5.1标准库异常类的层次结构 5.2使用标准库异常类的优点 6.异常的优缺点 6.1C异常的优点 6.2C异常的缺点 7.结语 图像由AI生成  0.前言 在软件开发过程中错误处理是不可避免的。有效的错误处理机制不仅能提高程序的健壮性还能使代码更易于维护。C11引入了强大的异常处理机制使得程序员可以更优雅地处理异常情况。本文将详细介绍C11中的异常处理机制帮助读者更好地理解和应用这一特性。 1.C语言传统错误处理方式 在C语言中错误处理主要通过返回值和错误码来实现。C语言没有内置的异常处理机制因此程序员需要手动检查和处理每个可能出现的错误。以下是一些常见的错误处理方式 1.1使用返回值 函数可以通过返回值来指示操作是否成功。如果操作失败函数通常返回一个特定的错误码。调用者需要检查返回值并采取相应的措施。 #include stdio.hint divide(int a, int b, int *result) {if (b 0) {return -1; // 返回错误码}*result a / b;return 0; // 成功 }int main() {int res;if (divide(10, 2, res) 0) {printf(Result: %d\n, res);} else {printf(Error: Division by zero\n);}return 0; }在上面的例子中divide函数返回一个错误码如果除数为零则返回-1表示错误。调用者通过检查返回值来确定是否发生了错误。 1.2使用全局变量 另一种方法是使用全局变量来存储错误码例如errno。这是C标准库提供的一个全局变量用于表示最近一次函数调用中的错误代码。 #include stdio.h #include errno.hint divide(int a, int b, int *result) {if (b 0) {errno EINVAL; // 设置错误码return -1;}*result a / b;return 0; }int main() {int res;if (divide(10, 0, res) 0) {printf(Result: %d\n, res);} else {perror(Error); // 打印错误信息}return 0; }在这个例子中当除数为零时divide函数设置全局变量errno并返回错误。调用者使用perror函数打印错误信息该函数会根据errno的值输出相应的错误描述。 1.3使用断言 对于某些情况下的错误处理可以使用assert宏来检查程序中的假设。如果条件为假程序会打印错误信息并中止执行。这种方法通常用于开发和调试阶段。 #include assert.hint divide(int a, int b) {assert(b ! 0); // 检查条件return a / b; }int main() {int result divide(10, 2);printf(Result: %d\n, result);return 0; }1.4优缺点 使用返回值和错误码进行错误处理有以下优缺点 优点 简单直观易于理解和实现。无需额外的语言支持可以在任何C编译器上使用。 缺点 错误码难以统一容易引起混淆。需要额外的代码来检查错误码增加了代码的复杂度。忽略错误检查可能导致程序运行错误。错误处理分散在各个函数调用处不利于维护和调试。 2.C异常的概念 异常是一种处理错误的方式当一个函数发现自己无法处理的错误时就可以抛出异常让函数的直接或间接的调用者处理这个错误。 throw: 当问题出现时程序会抛出一个异常。这是通过使用throw关键字来完成的。catch: 在您想要处理问题的地方通过异常处理程序捕获异常。catch关键字用于捕获异常可以有多个catch进行捕获。try: try块中的代码标识将被激活的特定异常它后面通常跟着一个或多个catch块。 如果有一个块抛出一个异常捕获异常的方法会使用try和catch关键字。try块中放置可能抛出异常的代码try块中的代码被称为保护代码。使用try/catch语句的语法如下所示 try {// 保护的标识代码 } catch (ExceptionName e1) {// catch 块 } catch (ExceptionName e2) {// catch 块 } catch (ExceptionName eN) {// catch 块 }在C中异常处理机制使得错误处理更加结构化和集中化。throw语句可以抛出任何类型的对象通常是异常类的实例。标准库提供了多种异常类可以直接使用如std::exception, std::runtime_error, std::logic_error等。用户还可以自定义异常类以适应特定需求。 以下是一个简单的例子 #include iostream #include stdexceptvoid divide(int a, int b) {if (b 0) {throw std::runtime_error(Division by zero);}std::cout Result: a / b std::endl; }int main() {try {divide(10, 0);} catch (const std::runtime_error e) {std::cerr Error: e.what() std::endl;}return 0; }在上面的例子中如果除数为零divide函数会抛出一个std::runtime_error异常。main函数中的try块捕获该异常并输出错误信息。 3.异常的使用 3.1异常的抛出和捕获 3.1.1异常的抛出和匹配原则 抛出异常: 异常是通过抛出对象而引发的该对象的类型决定了应激活哪个catch的处理代码。选择处理代码: 被选中的处理代码是调用栈中与该对象类型匹配且位置最接近抛出异常位置的那一个。异常对象的生成和销毁: 抛出异常对象后会生成一个异常对象的拷贝因为抛出的异常对象可能是一个临时对象所以会生成一个拷贝对象这个拷贝的临时对象会在被catch以后销毁。这里的处理类似于函数的传值返回catch(...): 可以捕获任意类型的异常问题是不知道异常错误是什么。基类捕获: 实际中抛出和捕获的匹配原则有个例外并不都是类型完全匹配可以抛出其派生类对象使用基类捕获这个在实际中非常实用。 3.1.2在函数调用链中异常栈展开匹配原则 首先检查throw本身是否在try块内部如果是再查找匹配的catch语句。如果有匹配的则调用catch的地方进行处理。如果没有匹配的catch则退出当前函数栈继续在调用函数的栈中进行查找匹配的catch不断重复上述过程。若到达main函数的栈依旧没有匹配的则终止程序。如果到达main函数的栈依旧没有匹配的则终止程序。找到匹配的catch子句并处理以后会继续沿catch子句后面继续执行。 在下面的示例中有三个函数func1(), func2(), func3()。在func2()中调用func1(), func3()中调用func2(), main()中调用func3()。如果在func1()中抛出一个异常在main()中用catch语句捕获。 void func1() {throw std::runtime_error(Error occurred); }void func2() {func1(); }void func3() {func2(); }int main() {try {func3();} catch (const std::runtime_error e) {std::cerr Caught: e.what() std::endl;}return 0; }栈展开过程如下 首先检查throw本身是否在try块内部如果是再查找匹配的catch语句。如果有匹配的则处理。如果没有匹配的catch则退出当前函数栈继续在调用函数的栈中进行查找匹配的catch不断重复上述过程。若到达main函数的栈依旧没有匹配的则终止程序。找到匹配的catch子句并处理以后会继续沿catch子句后面继续执行。 通过这个过程我们可以看到异常处理如何在调用链中展开并最终被捕获和处理。 3.2异常的重新抛出 有可能单个的catch不能完全处理一个异常在进行一些校正处理以后希望再交给更外层的调用链函数来处理catch则可以通过重新抛出将异常传递给更上层的函数进行处理。 重新抛出异常可以使用throw关键字这样可以将捕获的异常再抛出以便在更高层次的catch块中处理。这种方法对于需要在多个层次上处理异常的情况非常有用。 以下是一个例子展示了如何重新抛出异常 #include iostream #include stdexcept// 第一级处理 void level1() {try {throw std::runtime_error(Error occurred at level 1);} catch (const std::runtime_error e) {std::cerr Caught in level1: e.what() std::endl;// 重新抛出异常throw;} }// 第二级处理 void level2() {try {level1();} catch (const std::runtime_error e) {std::cerr Caught in level2: e.what() std::endl;// 再次重新抛出异常throw;} }// 第三级处理最高层次 int main() {try {level2();} catch (const std::runtime_error e) {std::cerr Caught in main: e.what() std::endl;}return 0; }输出 Caught in level1: Error occurred at level 1 Caught in level2: Error occurred at level 1 Caught in main: Error occurred at level 1  在这个例子中异常首先在level1函数中被抛出并捕获。level1函数中的catch块捕获异常后输出错误信息并重新抛出异常。接着level2函数中的catch块捕获重新抛出的异常输出错误信息后再次重新抛出。最后main函数中的catch块捕获到来自level2的异常并输出最终的错误信息。 这种方法确保了异常在不同的层次上得到处理允许每个层次的代码对异常进行适当的处理和记录。 3.3异常安全 在编写C代码时异常安全性是一个非常重要的概念。它涉及确保程序在抛出异常时仍然保持一致的状态。实现异常安全性的方法主要包括以下几点 构造函数完成对象的构造和初始化: 最好不要在构造函数中抛出异常否则可能导致对象不完整或没有完全初始化。 析构函数主要完成资源的清理: 最好不要在析构函数内抛出异常否则可能导致资源泄漏例如内存泄漏、句柄未关闭等。 C中异常经常会导致资源泄漏的问题比如在new和delete中抛出了异常导致内存泄漏。在lock和unlock之间抛出了异常导致死锁。C经常使用RAIIResource Acquisition Is Initialization来解决以上问题。RAII通过在对象的生命周期内绑定资源管理以确保资源在对象销毁时被正确释放从而避免资源泄漏和其他异常处理问题。 class Resource { public:Resource() {// 构造函数中完成资源的分配和初始化resource_ new int[100];}~Resource() {// 析构函数中完成资源的释放delete[] resource_;} private:int* resource_; };在这个示例中Resource类的构造函数分配了资源而析构函数负责释放资源确保无论发生什么情况资源都能得到正确的管理。 3.4异常规范 异常规范的目的是为了让函数使用者知道该函数可能抛出的异常有哪些。在C98中可以在函数的后面加上throw(类型)列出这个函数可能抛出的所有异常类型。C11引入了noexcept来表示函数不抛出异常。 // 这里表示这个函数会抛出A, B, C, D中的某种类型的异常 void fun() throw(A, B, C, D);// 这里表示这个函数会抛出bad_alloc的异常 void* operator new(std::size_t size) throw(std::bad_alloc);// 这里表示这个函数不会抛出异常 void operator delete(void* ptr) throw();// C11中新增的noexcept表示不会抛出异常 void thread() noexcept; void thread(thread) noexcept;在这个示例中fun函数可能抛出多种类型的异常而operator new函数可能抛出std::bad_alloc异常。operator delete函数和thread函数则明确表示它们不会抛出任何异常。 4.自定义异常体系 在实际应用中很多公司都会自定义自己的异常体系进行规范的异常管理。这是因为在一个项目中如果每个人都随意抛出异常那么外层的调用者就基本无法处理这些异常程序的健壮性和可维护性会大大降低。因此实际中通常会定义一套继承的规范体系这样大家抛出的都是继承的派生类对象捕获时只需要捕获一个基类即可。 自定义异常类示例 通常自定义异常体系的做法是创建一个基类并从这个基类派生出不同类型的异常类。这样可以在一个统一的框架内处理不同类型的异常。 #include iostream #include exception// 自定义基类异常 class MyException : public std::exception { public:virtual const char* what() const noexcept override {return MyException occurred;} };// 派生类异常类型1 class MyExceptionType1 : public MyException { public:const char* what() const noexcept override {return MyExceptionType1 occurred;} };// 派生类异常类型2 class MyExceptionType2 : public MyException { public:const char* what() const noexcept override {return MyExceptionType2 occurred;} };// 使用自定义异常体系 void functionThatThrows() {throw MyExceptionType1(); }int main() {try {functionThatThrows();} catch (const MyException e) {std::cerr Caught: e.what() std::endl;}return 0; }在这个示例中MyException是基类异常MyExceptionType1和MyExceptionType2是从基类继承的派生类异常。通过这种方式当发生异常时调用者可以捕获基类MyException从而处理所有类型的派生类异常。 这种异常体系的优点是结构清晰扩展性强便于管理和维护。在实际应用中自定义异常体系有助于规范异常处理流程提高代码的可读性和可靠性。  5.C标准库的异常体系 C标准库提供了一套丰富的异常类体系用于处理各种常见的错误情况。这些异常类大多数继承自std::exception基类并根据不同的错误类型派生出多个子类。了解和使用这些标准异常类可以使代码更具可读性和一致性。 5.1标准库异常类的层次结构 C标准库的异常类层次结构如下 std::exception: 所有标准库异常的基类。它定义了一个虚函数what()用于返回异常的描述信息。 std::logic_error: 继承自std::exception表示程序逻辑错误。常见的派生类包括 std::invalid_argument: 表示无效参数。std::domain_error: 表示参数超出定义域。std::length_error: 表示长度错误。std::out_of_range: 表示超出范围。 std::runtime_error: 继承自std::exception表示程序运行时错误。常见的派生类包括 std::range_error: 表示范围错误。std::overflow_error: 表示算术溢出错误。std::underflow_error: 表示算术下溢错误。 以下是使用标准库异常类的示例 #include iostream #include stdexceptvoid functionThatThrows() {throw std::invalid_argument(Invalid argument provided); }int main() {try {functionThatThrows();} catch (const std::invalid_argument e) {std::cerr Caught std::invalid_argument: e.what() std::endl;} catch (const std::exception e) {std::cerr Caught std::exception: e.what() std::endl;}return 0; }在这个示例中functionThatThrows函数抛出了一个std::invalid_argument异常。在main函数中使用try-catch块捕获该异常并输出相应的错误信息。 5.2使用标准库异常类的优点 一致性: 使用标准库异常类可以使代码在处理异常时保持一致性减少混乱和错误。可读性: 标准库异常类名称直观能够明确表达异常的含义提高代码的可读性。复用性: 标准库异常类经过充分测试和验证具有高可靠性减少了自定义异常类的工作量。 6.异常的优缺点 6.1C异常的优点 精确定位错误: 异常处理机制可以清晰准确地展示出错误的各种信息甚至可以包含堆栈调用的信息这样有助于更好地定位程序的bug。 简化错误处理流程: 使用返回值来传递错误信息在深层的函数调用链中会变得非常复杂。相比之下异常处理机制可以直接将异常传递到最顶层的捕获块无需逐层检查错误返回值。 示例代码 int ConnectSql() {// 用户名密码错误if (...) return 1;// 权限不足if (...) return 2; }int ServerStart() {int ret ConnectSql();if (ret 0)return ret;int fd socket();if (fd 0)return errno;return 0; }int main() {int result ServerStart();if (result 0) {std::cerr Error: result std::endl;return result;}// 其他逻辑return 0; }使用异常处理机制后的代码 class MyException : public std::exception { public:const char* what() const noexcept override {return MyException occurred;} };void ConnectSql() {throw MyException(); }void ServerStart() {ConnectSql(); }int main() {try {ServerStart();} catch (const MyException e) {std::cerr Caught: e.what() std::endl;}// 其他逻辑return 0; }支持第三方库的异常处理: 很多第三方库如Boost, GTest, GMock等都使用异常来报告错误。使用这些库时异常处理可以无缝衔接。 适合部分函数的错误处理: 一些函数例如构造函数没有返回值因此无法使用错误码方式处理错误。使用异常可以解决这个问题。 6.2C异常的缺点 执行流混乱: 异常会导致程序的执行流突然跳转使代码的控制流变得复杂。这在调试和分析程序时会增加难度。 性能开销: 虽然在现代硬件上这个影响可以忽略不计但异常处理机制确实会带来一定的性能开销。 资源管理复杂: C没有垃圾回收机制资源需要手动管理。如果异常处理不当可能会导致资源泄漏和死锁等问题。这需要使用RAII资源获取即初始化模式来管理资源但学习成本较高。 异常体系复杂: C标准库的异常体系定义复杂且难以掌握导致很多开发者选择自己定义异常体系增加了代码的混乱度。 滥用异常: 不当的异常使用会导致代码难以维护和理解。因此使用异常时需要遵循一定的规范抛出异常类应继承自一个基类尽量明确函数会抛出哪些异常。 总的来说异常处理机制的优点远大于其缺点因此在工程实践中我们鼓励使用异常处理。另外面向对象的编程语言基本都支持异常处理这也表明异常处理是一个发展趋势。通过正确使用异常处理机制可以大大提高代码的健壮性和可维护性。 7.结语 C11的异常处理机制为程序员提供了一种强大的工具用于处理程序中的错误和异常。通过使用异常我们可以实现更加清晰、结构化和易于维护的代码显著提升程序的健壮性和可读性。尽管异常处理机制有其复杂性和潜在的性能开销但其优势远远超过了这些缺点。掌握并合理使用C11的异常处理机制将使我们的开发工作更加高效和可靠。希望本文能帮助读者更好地理解和应用C11的异常处理特性从而编写出更优秀的程序。
http://www.w-s-a.com/news/445611/

相关文章:

  • 公司网站开发费用账务处理ucenter wordpress
  • 六站合一的优势少儿编程机构
  • 软件开发与网站开发学做美食网站哪个好
  • 网站搜索 收录优化百度推广页面投放
  • 响应式网站的优点浙江省网站域名备案
  • 网站安全 扫描深圳被点名批评
  • 在哪个网站可以一对一做汉教网站优化策略
  • 龙岩做网站的顺企网宁波网站建设
  • 昆山网站建设河北连锁餐厅vi设计公司
  • 新蔡县住房和城乡建设局网站南昌租房网地宝网
  • 南宁做网站费用iis编辑网站绑定
  • 家用宽带做网站服务器建网站费用明细
  • 电商 网站 降低 跳出率 措施 效果书画院网站模板
  • 兰州移动官网网站建设上海工商网上公示系统
  • 在招聘网站里做电话销售免费空间可以上传网站吗
  • 梅州建站怎么做中国建设银行官网下载
  • 网站静态化设计广州网站备案方案
  • 西安网络技术有限公司网站扬中网站建设方案
  • 青海省教育厅门户网站wordpress core
  • idc科技公司网站模板蜜雪冰城网络营销案例分析
  • 微信与网站对接手机软件怎么做
  • 户县网站建设珠海专业制作网站
  • 麦当劳的网站优化建议猎头公司工作怎么样
  • 合肥地区网站制作网页浏览器打不开
  • 做网站的不给ftp网站如何做触屏滑动
  • wordpress statraq重庆百度优化
  • 企业网站官网英文WordPress站点切换为中文
  • 服装公司网站定位一点号自媒体平台
  • 密云微网站建设汽车之家手机官网首页
  • 多语言外贸网站制作苏州建设网站微信公众号