相关疑难解决方法(0)

如何在C++中使用数组?

C++从C继承了数组,几乎无处不在.C++提供了易于使用且不易出错的抽象(std::vector<T>自C++ 98和C++ 11std::array<T, n>以来),因此对数组的需求并不像在C中那样频繁出现.但是,当您阅读遗产时代码或与用C编写的库交互,你应该牢牢掌握数组如何工作.

本FAQ分为五个部分:

  1. 类型级别的数组和访问元素
  2. 数组创建和初始化
  3. 赋值和参数传递
  4. 多维数组和指针数组
  5. 使用数组时常见的陷阱

如果您觉得此常见问题解答中缺少重要内容,请写下答案并将其作为附加部分链接到此处.

在下文中,"数组"表示"C数组",而不是类模板std::array.假定了C声明符语法的基本知识.请注意,面对异常,手动使用newdelete如下所示是非常危险的,但这是另一个常见问题解答的主题.

(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)

c++ arrays pointers c++-faq multidimensional-array

469
推荐指数
5
解决办法
12万
查看次数

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

RAII和C++中的智能指针

在使用C++的实践中,什么是RAII,什么是智能指针,如何在程序中实现这些以及将RAII与智能指针一起使用有什么好处?

c++ smart-pointers raii

189
推荐指数
4
解决办法
6万
查看次数

RAII与例外

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

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

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

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

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

附录

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

c++ destructor exception raii

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

除了C++之外,其他语言的程序员是否使用,了解或了解RAII?

我注意到RAII在Stackoverflow上得到了很多关注,但在我的圈子里(主要是C++),RAII非常明显,就像问什么是类或析构函数一样.

所以我真的很好奇,如果那是因为我每天都被硬核C++程序员所包围,并且RAII一般不是众所周知的(包括C++),或者如果Stackoverflow上的所有这些问题都归因于事实我现在正在与没有使用C++成长的程序员联系,而在其他语言中,人们只是不使用/了解RAII?

c++ language-agnostic raii

33
推荐指数
7
解决办法
6614
查看次数

使用在C++中动态分配的数组有什么问题?

如下代码:

int size = myGetSize();
std::string* foo;
foo = new std::string[size];
//...
// using the table
//...
delete[] foo;
Run Code Online (Sandbox Code Playgroud)

我听说在某些情况下这样的使用(不是这个代码,但是整个动态分配)可能是不安全的,并且只能用于RAII.为什么?

c++ dynamic-allocation

30
推荐指数
3
解决办法
4881
查看次数

创建没有"new"运算符的类的新实例

只是一个简单的问题.正如标题所示,我只使用"new"运算符来创建类的新实例,所以我想知道其他方法是什么以及如何正确使用它.

c++ class

20
推荐指数
2
解决办法
4万
查看次数

什么是C++中的"哨兵对象"?

回答这个问题,并Potatoswatter 回答过的

现代C++等价物将是一个哨兵对象:在函数的开头构造它,其构造函数实现call(),并在返回(或异常退出)时,它的析构函数实现

我不熟悉在C++中使用sentry对象.我认为它们仅限于输入和输出流.

有人可以向我解释C++哨兵对象以及如何将它们用作类中一个或多个方法的周围拦截器吗?

即如何做到这一点?

Sentry对象确实非常相似.一方面,它们需要显式实例化(并且通过它),但另一方面,您可以添加它们,这样它们不仅可以检查类的不变量,还可以检查手头函数的一些前/后条件.

c++ idioms

14
推荐指数
1
解决办法
3962
查看次数

在构造函数中创建的模式名称,在析构函数中删除(C++)

传统上,在C++中,您将在构造函数中创建任何依赖项,并在析构函数中删除它们.

class A
{
 public:
    A() { m_b = new B(); }
    ~A() { delete m_b; }
 private:
    B* m_b;
};
Run Code Online (Sandbox Code Playgroud)

这种技术/资源获取模式,它有一个共同的名称吗?
我很确定我已经在某处读过它但现在找不到它.

编辑:
正如许多人所指出的,这个类是不完整的,应该真正实现一个复制构造函数和赋值运算符.
最初,我故意将其遗漏,因为它与实际问题无关:模式的名称.但是,为了完整性和鼓励良好实践,接受的答案就是它.

c++ design-patterns raii

10
推荐指数
2
解决办法
852
查看次数

在堆上分配内存的函数原型(C/C++)

我对C++很新,所以这可能是一个初学者的问题.它认为做某事的"适当"风格我怀疑是相当普遍的.

我正在编写一个函数,在执行其职责时,在堆上分配内存以供调用者使用.我很好奇这个函数的原型应该是什么样子.现在我有:

int f(char** buffer);
Run Code Online (Sandbox Code Playgroud)

要使用它,我会写:

char* data;
int data_length = f(&data);
// ...
delete[] data;
Run Code Online (Sandbox Code Playgroud)

但是,我正在向指针传递指针的事实让我觉得我可能做错了.

有人关心开导我吗?

c c++ heap buffer

6
推荐指数
2
解决办法
1122
查看次数