相关疑难解决方法(0)

我在哪里可以找到当前的C或C++标准文档?

对于许多问题,答案似乎可以在"标准"中找到.但是,我们在哪里找到它?最好是在线.

谷歌搜索有时会觉得徒劳,尤其是对于C标准,因为他们在编程论坛的大量讨论中被淹没.

要开始这个,因为这些是我现在正在搜索的,那里有很好的在线资源:

  • C89
  • C99
  • C11
  • C++ 98
  • C++ 03
  • C++ 11
  • C++ 14

c c++ standards c++-faq

394
推荐指数
8
解决办法
12万
查看次数

260
推荐指数
10
解决办法
20万
查看次数

我需要手动关闭ifstream吗?

close()我使用时需要手动拨打电话std::ifstream吗?

例如,在代码中:

std::string readContentsOfFile(std::string fileName) {

  std::ifstream file(fileName.c_str());

  if (file.good()) {
      std::stringstream buffer;
      buffer << file.rdbuf();
      file.close();

      return buffer.str();
  }
  throw std::runtime_exception("file not found");
}
Run Code Online (Sandbox Code Playgroud)

我需要file.close()手动拨打电话吗?不应该ifstream使用RAII来关闭文件?

c++ raii ifstream

187
推荐指数
5
解决办法
6万
查看次数

RAII与例外

我们在C++中使用RAII的次数越多,我们就越发现自己的析构函数会进行非平凡的释放.现在,解除分配(终结,但是你想要调用它)可能会失败,在这种情况下,异常实际上是让楼上的任何人知道我们的释放问题的唯一方法.但是再说一次,抛出析构函数是一个坏主意,因为在堆栈展开期间可能会抛出异常.std::uncaught_exception()让你知道什么时候发生,但不是更多,所以除了让你在终止之前记录一条消息之外你没有太多可以做的,除非你愿意让你的程序处于未定义的状态,其中一些东西被解除分配/最终化而一些不是.

一种方法是使用无抛出析构函数.但在许多情况下,这只是隐藏了一个真正的错误.例如,我们的析构函数可能会因为抛出某些异常而关闭一些RAII管理的数据库连接,并且这些数据库连接可能无法关闭.这并不一定意味着我们可以在此时终止程序.另一方面,记录和跟踪这些错误并不是每个案例的真正解决方案; 否则我们就不需要开始例外了.使用无抛出析构函数,我们还发现自己必须创建应该在销毁之前调用的"reset()"函数 - 但这只会破坏RAII的整个目的.

另一种方法是让程序终止,因为这是你可以做的最可预测的事情.

有些人建议链接异常,以便一次可以处理多个错误.但老实说,我从来没有真正看到用C++完成的工作,我也不知道如何实现这样的东西.

所以它是RAII或例外.不是吗?我倾向于无抛出的破坏者; 主要是因为它保持简单(r).但我真的希望有一个更好的解决方案,因为,正如我所说,我们使用RAII的次数越多,我们发现自己越多地使用执行非平凡事情的dtors.

附录

我正在添加链接到我发现的有趣的主题文章和讨论:

c++ destructor exception raii

48
推荐指数
4
解决办法
7380
查看次数

函数try块何时有用?

我想知道程序员何时使用函数try块.什么时候有用?

void f(int i)
try
{
   if ( i  < 0 ) 
      throw "less than zero";
   std::cout << "greater than zero" << std::endl;
}
catch(const char* e)
{
    std::cout << e << std::endl;
}

int main() {
        f(1);
        f(-1);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:(在ideone处)

greater than zero
less than zero
Run Code Online (Sandbox Code Playgroud)

编辑:因为有些人可能认为函数定义的语法不正确(因为语法看起来不熟悉),我要说它不是不正确的.它叫做function-try-block.参见C++标准中的§8.4/ 1 [dcl.fct.def].

c++ function function-try-block

36
推荐指数
6
解决办法
9144
查看次数

析构函数C++中的异常

我很清楚,不应该在析构函数中抛出任何异常.

但作为掌握这一概念的一部分,我编写了这个例子: -

#include <iostream>
using namespace std;

class A {
private: 
    int i;

public:
    A()
    {
        i = 10;
    }
    ~A()
    {
        throw 30;
    }
};
int main(){
    try{
        A();
        throw 10;
    }
    catch (int i){
        cout << i << endl;
        cout << "exception caught" << endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,这个程序应该通过调用std :: terminate()来终止,因为同时会有两个例外.但是,这个程序给出了以下输出: -

30
exception caught
Run Code Online (Sandbox Code Playgroud)

任何人都可以向我解释这背后的逻辑,为什么这不是终止?

c++ destructor exception-handling

36
推荐指数
2
解决办法
6043
查看次数

在析构函数中捕获异常

是否有可能使析构函数捕获异常然后重新抛出它们?
如果是这样,我将如何做到这一点,因为try声明没有明确的地方?

基本上,我想理想地做:

CMyObject::~CMyObject()  
{
    catch(...)    // Catch without a try.  Possible?
    {
        LogSomeInfo();
        throw;  // re-throw the same exception
    }
    // Normal Destructor operations
}
Run Code Online (Sandbox Code Playgroud)

背景
我有一个庞大的,复杂的应用程序,在某处抛出未处理的异常.我没有轻松访问main或顶级消息泵或任何类似的东西,所以没有容易捕获所有未处理的异常的地方.

我认为任何未处理的异常必须通过一堆析构函数,因为堆栈是解开的.所以,我正在考虑catch在析构函数中散布一堆语句.然后,至少我会知道抛出异常时正在播放的对象.但我不知道这是否可行,或者是否可取.

c++ destructor exception

26
推荐指数
3
解决办法
1511
查看次数

如果delete [] p失败会怎么样?

假设我有一个指向动态分配的10个元素数组的指针:

T* p = new T[10];
Run Code Online (Sandbox Code Playgroud)

后来,我想发布那个数组:

delete[] p;
Run Code Online (Sandbox Code Playgroud)

如果其中一个T析构函数抛出异常会发生什么?其他元素是否仍然被破坏?记忆会被释放吗?是否会传播异常,还是会终止程序执行?

同样地,当一个std::vector<T>被破坏而其中一个T析构者抛出时会发生什么?

c++ arrays memory-leaks exception resource-management

20
推荐指数
3
解决办法
1891
查看次数

可能STL迭代器方法抛出异常

析构函数可能不会抛出异常(因此在异常处理期间可以完成堆栈展开),并且必须释放分配给该对象的任何资源(因此不会泄漏资源).包含多个其他对象(或分配了多个资源)的对象的设计可能会在STL容器中记录指向它们的指针.因此析构函数将使用以下与迭代器相关的方法:

  • begin(),end()对于容器
  • operator++ 对于有效的迭代器
  • operator*或者operator->对于有效的迭代器

但是为了保证析构函数不会抛出异常并释放其资源,您需要依赖那些永远不会抛出异常的方法.

依赖那些从不抛出异常的方法是否安全?很难想象一个实际的实现会抛出异常,因为STL迭代器本质上是一个指针.但标准C++是否要求这些方法永远不会抛出异常?我没有在C++标准中找到明确的陈述.


编辑:有趣的情况是C++ 03,当你想拥有一个指向资源的容器.这样做有充分的理由; 例如,如果您有多态资源.正如BjörnPollex在他的回答中指出的那样,如果你使用一个资源容器(比如a std::list< Resource >)而不是一个指向资源的指针的容器,容器的析构函数将为你处理对象的破坏(释放)Resource.

c++ stl exception

18
推荐指数
2
解决办法
5397
查看次数

从析构函数抛出一个异常安全的vtable?

请考虑以下示例:

#include <csignal>

class A
{
public:
    virtual ~A() {}
    virtual void foo() = 0;
};

class B : public A
{
public:
    virtual ~B() { throw 5; } 
    virtual void foo() {}
};

int main(int, char * [])
{
    A * b = new B();

    try
    {
        delete b;
    }
    catch ( ... )
    {
        raise(SIGTRAP);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我一直认为(天真的我),当程序在这种情况下获得,进入catch部分,则对象B在这b点将会保留,因为它是相当合乎逻辑的例外,将有"取消"(如果编程安全)的析构函数的效果.但是当我试图在gdb中运行这个片段并且在catch部分中找到断点时,我看到B对象已经消失,只剩下一个基础对象,因为vtable看起来像这样:

(gdb) i vtbl b
vtable for 'A' @ 0x400cf0 (subobject …
Run Code Online (Sandbox Code Playgroud)

c++ exception-handling

17
推荐指数
2
解决办法
752
查看次数