小编Gre*_*ers的帖子

从析构函数中抛出异常

大多数人都说永远不会从析构函数中抛出异常 - 这样做会导致未定义的行为.Stroustrup指出"向量析构函数显式地为每个元素调用析构函数.这意味着如果元素析构函数抛出,向量破坏失败......实际上没有好的方法来防止从析构函数抛出的异常,所以库如果元素析构函数抛出",则不保证"(来自附录E3.2).

这篇文章似乎另有说法 - 抛出析构函数或多或少都没问题.

所以我的问题是 - 如果从析构函数抛出会导致未定义的行为,那么如何处理析构函数期间发生的错误?

如果在清理操作期间发生错误,您是否只是忽略它?如果它是一个可能在堆栈中处理但在析构函数中不正确的错误,那么从析构函数中抛出异常是否有意义?

显然,这类错误很少见,但可能.

c++ destructor exception raii

246
推荐指数
10
解决办法
11万
查看次数

为什么std :: stack默认使用std :: deque?

由于在堆栈中使用容器所需的唯一操作是:

  • 背部()
  • 推回()
  • pop_back()

为什么它的默认容器是deque而不是vector?

不要deque重新分配在front()之前给出元素缓冲区,以便push_front()是一个有效的操作吗?这些元素不会浪费,因为它们永远不会在堆栈的上下文中使用吗?

如果没有开销使用一个deque这种方式,而不是一个向量,为什么是priority_queue矢量不是一个deque也默认?(priority_queue需要front(),push_back()和pop_back() - 基本上与堆栈相同)


根据以下答案进行了更新:

似乎deque通常实现的方式是固定大小数组的可变大小数组.这使得比向量的增长速度(这需要重新分配和复制),所以对于像一个栈,所有关于添加和删除元素,双端队列可能是一个更好的选择.

priority_queue需要大量的索引,因为每个删除和插入需要你运行pop_heap()或push_heap().这可能使得向量成为更好的选择,因为添加元素仍然是分摊常数.

c++ containers stl

84
推荐指数
2
解决办法
1万
查看次数

Waitpid相当于超时?

想象一下,我有一个启动多个子进程的进程.父母需要知道孩子什么时候退出.

我可以使用waitpid,但是如果/当父需要退出时,我无法告诉阻塞的线程waitpid优雅地退出并加入它.让事情自己清理是件好事,但这可能不是什么大不了的事.

我可以用waitpidWNOHANG,然后睡了一段任意时间,以防止忙等待.然而,我只能知道一个孩子是否经常退出.在我的情况下,我知道孩子何时立即离开可能不是超级关键,但我想尽快知道...

我可以使用信号处理程序SIGCHLD,并在信号处理程序中执行当子项退出时要执行的任何操作,或者将消息发送到其他线程以执行某些操作.但是使用信号处理程序会稍微混淆代码流.

我真正想做的是使用waitpid一些超时,比如5秒.由于退出进程不是一个时间关键的操作,我可以懒惰地发出线程信号退出,同时仍然在waitpid其余时间阻塞它,随时准备做出反应.在linux中有这样的调用吗?在替代方案中,哪一个最好?


编辑:

基于回复的另一种方法是SIGCHLDpthread\ 来阻塞所有线程_sigmask().然后在一个线程中,sigtimedwait()一边寻找一边打电话SIGCHLD.这意味着我可以超时调用并检查线程是否应该退出,如果没有,则保持阻塞状态等待信号.一旦a SIGCHLD被传递到这个线程,我们可以立即对它做出反应,并且在等待线程的行中,不使用信号处理程序.

c c++ linux

47
推荐指数
5
解决办法
3万
查看次数

如何使用GNU autotools为"make check"创建测试

我正在使用GNU autotools来构建特定项目的构建系统.我想开始为验证编写自动化测试.我想输入"make check"让它自动运行这些.我的项目是用C++编写的,虽然我仍然对为其他语言编写自动化测试感到好奇.

这几乎与每个单元测试框架兼容(我在考虑使用cppunit)吗?如何将这些单元测试框架挂钩到make check中?我是否可以确保不需要安装单元测试软件来配置和构建项目的其余部分?

language-agnostic automated-tests unit-testing autotools

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

如何在linux中创建虚拟以太网设备?

我正在测试一个协议的实现,该协议使用以太网(而不是IP)在两台计算机之间进行通信.为了实际上不必拥有两台物理计算机,我想创建两个虚拟以太网接口.这些只能相互通信,因此一个端点程序将绑定到一个接口,另一个端点将绑定到另一个端点.

这可能吗,我该怎么办?

linux virtualization networking ethernet

24
推荐指数
2
解决办法
5万
查看次数

有没有一种方便的方法来将std :: pair包装为新类型?

通常我会发现自己使用std :: pair来定义两个相关量的逻辑分组作为函数参数/返回值.一些例子:row/col,tag/value等.

通常我应该滚动自己的类而不是仅使用std :: pair.当事情开始崩溃时很容易看到 - 当代码变得乱七八糟时,第一,第二,它很难记住什么是什么 - std::pair<int, int>传达的意义不如一种类型Position.

您发现什么是将std :: pair的功能包装在一个传达真正含义的类型中的最佳方法?

以下是我考虑过的一些事情:

typedef std::pair<int, int> Position;
Run Code Online (Sandbox Code Playgroud)

这至少在传递类型时为类型赋予了有意义的名称,但是类型没有强制执行,它仍然只是一对,并且大多数相同的问题仍然存在.然而,编写起来非常简单.

struct Position : public std::pair<int, int>
{
    typedef std::pair<int, int> Base;
    Position() : Base() {}
    Position(const Position &x) : Base(x) {}
    Position(int a, int b) : Base(a, b) {}

    int &row() { return first; }
    const int &row() const { return first; }

    int &col() { return second; }
    const int &col() const { return second; } …
Run Code Online (Sandbox Code Playgroud)

c++ stl

13
推荐指数
1
解决办法
3600
查看次数

使用boost :: random作为std :: random_shuffle的RNG

我有一个程序使用boost :: random的mt19937随机数生成器.我需要做一个random_shuffle,并希望为此生成的随机数来自这个共享状态,这样它们就可以确定为mersenne twister之前生成的数字.

我试过这样的事情:

void foo(std::vector<unsigned> &vec, boost::mt19937 &state)
{
    struct bar {
        boost::mt19937 &_state;
        unsigned operator()(unsigned i) {
            boost::uniform_int<> rng(0, i - 1);
            return rng(_state);
        }
        bar(boost::mt19937 &state) : _state(state) {}
    } rand(state);

    std::random_shuffle(vec.begin(), vec.end(), rand);
}
Run Code Online (Sandbox Code Playgroud)

但是我得到一个模板错误,用rand调用random_shuffle.但是这有效:

unsigned bar(unsigned i)
{
    boost::mt19937 no_state;
    boost::uniform_int<> rng(0, i - 1);
    return rng(no_state);
}
void foo(std::vector<unsigned> &vec, boost::mt19937 &state)
{
    std::random_shuffle(vec.begin(), vec.end(), bar);
}
Run Code Online (Sandbox Code Playgroud)

可能是因为它是一个实际的函数调用.但显然这并没有使国家不受最初的mersenne twister影响.是什么赋予了?有没有办法在没有全局变量的情况下做我想做的事情?

c++ stl boost-random

11
推荐指数
3
解决办法
6769
查看次数

C中的"CALLBACK"声明有什么作用?

我正在查看SDL库中的一些代码,并遇到了一个声明如下的函数:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Run Code Online (Sandbox Code Playgroud)

现在,我是德尔福编码器.没有hablo C muy bien,先生.但是我记得我的大学课程中有足够的语法来读它:

函数名称是WndProc.参数列表非常明显.函数返回类型是LRESULT.但是世界上那个"CALLBACK"在那里做什么呢?在Delphi中,任何函数都可以用作回调函数; 你只需要传递正确类型的函数指针.有什么特别的原因导致C不能这样工作吗?或者它意味着什么不同?

c windows syntax callback

10
推荐指数
1
解决办法
4220
查看次数

在GCC中实现通用原子加载或存储的更好方法?

我知道GCC的内置原子操作:http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Atomic-Builtins.html

但是这个列表不包括加载和存储等非常简单的操作.我可以在内联汇编的有限架构上实现这些(事实上对于许多像x86一样,它们基本上只是普通的mov),但是在一般情况下没有比这样的更好的方法:

// returns the value at ptr
void *atomic_load_ptr(void **ptr)
{
    return __sync_fetch_and_add(ptr, 0);
}

// returns old value int ptr after setting it to newval
void *atomic_store_ptr(void **ptr, void *newval)
{
    void *oldval = atomic_load_ptr(ptr)
    void *oldval2;
    do {
        oldval2 = oldval;
    } while ((oldval = __sync_val_compare_and_swap(ptr, oldval, newval)) != oldval2);
    return oldval;
}
Run Code Online (Sandbox Code Playgroud)

c gcc atomic

10
推荐指数
1
解决办法
3005
查看次数

为什么"long*"和"int*"在32位代码中不兼容?

我想知道为什么以下代码无法编译:

void foo_int(int *a) { }
void foo_long(long *a) { }

int main()
{
    int i;
    long l;

    foo_long(&i);
    foo_int(&l);
}
Run Code Online (Sandbox Code Playgroud)

我正在使用GCC,并且这两个调用都不能在C或C++中工作.由于它是一个32位系统,因此intlong都是带符号的32位整数(可以在编译时使用sizeof进行验证).

我问的原因是我有两个单独的头文件,都不在我的控制之下,而且有一个像:typedef unsigned long u32;和另一个:typedef unsigned int uint32_t;.声明基本上是兼容的,除非我在上面的代码片段中使用它们作为指针,我必须显式转换.

知道为什么会这样吗?

c c++

8
推荐指数
4
解决办法
2231
查看次数