小编Fab*_*orr的帖子

在C++中使用assert()是不好的做法?

我倾向于在我的C++代码中添加许多断言,以便在不影响发布版本性能的情况下简化调试.现在,assert是一个纯C宏设计,没有考虑到C++机制.

另一方面std::logic_error,C++定义了在程序逻辑中存在错误(因此名称)的情况下抛出的内容.抛出一个实例可能只是一个完美的,更多的C++替代品assert.

问题是,assert并且abort两者都立即终止程序而不调用析构函数,因此跳过清理,而手动抛出异常会增加不必要的运行时成本.解决这个问题的一种方法是创建一个自己的断言宏SAFE_ASSERT,它就像C对应物一样工作,但在失败时抛出异常.

我可以想到关于这个问题的三种看法:

  • 坚持C的主张.由于程序立即终止,因此更改是否正确展开并不重要.此外,#define在C++中使用s同样糟糕.
  • 抛出异常并在main()中捕获它.允许代码在程序的任何状态下跳过析构函数都是不好的做法,必须不惜一切代价避免,并且调用terminate()也是如此.如果抛出异常,则必须捕获它们.
  • 抛出异常并让它终止程序. 终止程序的例外是可以的,并且由于NDEBUG这种情况在发布版本中永远不会发生.捕获是不必要的,并公开内部代码的实现细节main().

这个问题有明确的答案吗?有专业的参考吗?

编辑:跳过析构函数当然没有未定义的行为.

c++ assert coding-style

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

在迭代递归结构时无法获得可变引用:不能一次多次借用可变引用

我试图迭代地导航递归数据结构,以便在某个位置插入元素.根据我的有限理解,这意味着对结构的根进行可变引用,并通过对其跟随者的引用连续替换它:

type Link = Option<Box<Node>>;

struct Node {
    next: Link
}

struct Recursive {
    root: Link
}

impl Recursive {
    fn back(&mut self) -> &mut Link {
        let mut anchor = &mut self.root;
        while let Some(ref mut node) = *anchor {
            anchor = &mut node.next;
        }
        anchor
    }
}
Run Code Online (Sandbox Code Playgroud)

(Rust操场链接)

但是,这失败了:

error[E0499]: cannot borrow `anchor.0` as mutable more than once at a time
  --> src/main.rs:14:24
   |
14 |         while let Some(ref mut node) = *anchor {
   |                        ^^^^^^^^^^^^
   |                        | …
Run Code Online (Sandbox Code Playgroud)

mutable rust borrowing

16
推荐指数
3
解决办法
2405
查看次数

const-of-const和指向const的指针的重载函数

我可以使用模板函数捕获数组及其(编译时)大小,如下所示:

template<int N>
void foo(const int (&)[N]) {
    std::cout << "foo(const int (&)[N])\n";
}
Run Code Online (Sandbox Code Playgroud)

但是,我想重载foo以允许指向const的指针,以便在数组类型上调用函数时使用第一个重载,而在直接调用指针时调用第二个重载.

void foo(const int *) {
    std::cout << "foo(const int *)\n";
}

int main() {
    int a[1] = { 0 };
    foo(a);
    const int b[1] = { 0 };
    foo(b);
}
Run Code Online (Sandbox Code Playgroud)

Try it on ideone

这里,第一个重载被调用a,第二个过载被调用b.

我的猜测是,a编译器必须执行转换为const,这意味着它foo(const int *)不是一个完美的匹配,但我已经迷失了为什么这甚至不是一个模糊的函数调用.

如何更改代码,以便在两种情况下都调用第一个重载?

c++ arrays templates pointers overloading

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

为什么noexcept构造函数需要实例化析构函数?

在下面的代码中,wrapper<T>声明了一个包含a 的对象movable<T>,其中T是一个不完整的类型.构造析构函数movable是为了在没有完全知识的情况下无法实例化T,但是wrapper析构函数只是向前声明,这意味着如果~movable()在定义的时候实例化它就足够了~wrapper().

#include <utility>

template<class T>
struct movable {
    movable() noexcept = default;
    ~movable() noexcept { (void) sizeof(T); }
    movable(const movable&) noexcept = delete;
    movable(movable &&) noexcept = default;
};

template<class T>
class wrapper {
public:
    movable<T> m;
    wrapper() noexcept = default;
    wrapper(wrapper &&) noexcept = default;
    ~wrapper();
};

struct incomplete;

int main() {
    /* extern */ wrapper<incomplete> original;
    wrapper<incomplete> copy(std::move(original));
}
Run Code Online (Sandbox Code Playgroud)

(在这里试试)

但是, …

c++ c++11

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

如何在 GTK+3 中主题化标题栏关闭按钮?

我想用所谓的“标题栏”更改 GTK+3 窗口上关闭按钮的样式,其中窗口在没有装饰的情况下呈现,GTK 组成标题栏和小部件。

“X”关闭按钮是什么类型的元素,它属于哪些 CSS 类(如果有)?

截屏

请注意,这不是窗口管理器主题的一部分,而是实际由 GTK+ 绘制的。

gtk themes gtk3

8
推荐指数
2
解决办法
7469
查看次数

获取完整的C++编译器命令行

在CMake中,C++编译器的标志可以通过各种方式受到影响:CMAKE_CXX_FLAGS手动设置,使用add_definitions(),强制某个C++标准等等.

为了使用不同的规则(在我的情况下是预编译的头)在同一个项目中编译目标,我需要重现用于编译add_executable()由此目录中的命令添加的文件的确切命令.

读取CMAKE_CXX_FLAGS只返回显式设置的值,CMAKE_CXX_FLAGS_DEBUG兄弟姐妹只列出默认的Debug/Release选项.有一个特殊的功能,检索标志从add_definitions()add_compiler_options(),但没有似乎能够返回最终的命令行.

如何将传递给编译器的所有标志都放入CMake变量?

cmake

8
推荐指数
1
解决办法
1635
查看次数

警告类成员自我初始化

看看这段C++代码:

class Foo
{
    int a;

    public: Foo(int b): a(a) {}
};
Run Code Online (Sandbox Code Playgroud)

显然,开发商意味着初始化ab而非a本身,这是一个相当困难的现场错误.

Clang ++会警告这个可能的错误,而GCC不会,即使启用了其他警告:

$ clang++ -c init.cpp 
init.cpp:5:27: warning: field is uninitialized when used here [-Wuninitialized]
    public: Foo(int b): a(a) {}
                        ^

$ g++ -Wall -Wuninitialized -Winit-self -c init.cpp 
$
Run Code Online (Sandbox Code Playgroud)

有没有机会为g ++启用相同的输出?

c++ gcc warnings initialization compiler-options

5
推荐指数
1
解决办法
1849
查看次数

继承虚拟基类的构造函数

虚拟基类在最派生的类中初始化,所以我的猜测是继承基类的构造函数也应该工作:

struct base {
    base(int) {}
};

struct derived: virtual base {
    using base::base;
};

derived d(0);
Run Code Online (Sandbox Code Playgroud)

但是,这无法使用GCC 5.2.0进行编译,GCC 5.2.0尝试查找base::base(),但与Clang 3.6.2一起正常工作.这是GCC中的错误吗?

c++ gcc g++ virtual-inheritance c++11

5
推荐指数
1
解决办法
283
查看次数

在结构中指定函数指针类型的生命周期

我有一个foo定义如下的函数:

fn foo<'a>(a: &'a i32, b: &i32) -> &'a i32 { a }
Run Code Online (Sandbox Code Playgroud)

我想在结构中存储指向该函数的指针:

struct S {
    f: fn(a: &i32, b: &i32) -> &i32,
}
Run Code Online (Sandbox Code Playgroud)

因为有两个输入生命周期,所以无法推断结果生命周期:

error[E0106]: missing lifetime specifier
  |
2 |     f: fn(a: &i32, b: &i32) -> &i32,
  |                                ^ expected lifetime parameter
  |
  = help: this function's return type contains a borrowed value,
    but the signature does not say whether it is borrowed from a or b
Run Code Online (Sandbox Code Playgroud)

当我问编译器foo的类型时,它也不是很有帮助:

let () = foo;
Run Code Online (Sandbox Code Playgroud)

给我 …

function-pointers lifetime rust

5
推荐指数
1
解决办法
838
查看次数

为SIGFPE设置标志并继续执行忽略FPE

在数值应用程序中,我想知道计算完成后是否发生浮点异常.默认情况下,将以静默方式忽略浮点除法和无效操作.

我的尝试是启用我关心的FPE,通过设置标志来处理SIGFPE并再次禁用它们以允许继续执行:

#include <fenv.h>
#include <signal.h>
#include <stdio.h>

int caught = 0;
struct sigaction old_sa;
/* (2) */ fenv_t fenv_hold;

void sighandler()
{
    caught = 1;
    printf("Caught in handler, disabling\n");
    /* (1) */ fedisableexcept(FE_ALL_EXCEPT);
    /* (2) */ feholdexcept(&fenv_hold);
    sigaction(SIGFPE, &old_sa, NULL);
}

int main(void)
{
    struct sigaction sa;
    volatile double a=1, b=0;

    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = sighandler;
    sigaction(SIGFPE, &sa, &old_sa);

    feenableexcept(FE_DIVBYZERO);
    printf("Dividing by zero..\n");
    a/=b;
    printf("Continuing\n");
}
Run Code Online (Sandbox Code Playgroud)

我采取了两种方法,第一种标记(1),第二种标记(2).它们都没有按预期工作.

输出:

Dividing by zero..
Caught in …
Run Code Online (Sandbox Code Playgroud)

c linux floating-point signals

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

通过自动工具查询pkg-config变量

要安装目录文件,我想获得Glade(UI设计器)的目录,如下所示:

$ pkg-config --variable=catalogdir gladeui-2.0
/usr/share/glade/catalogs
Run Code Online (Sandbox Code Playgroud)

但是在我的Makefile.am中的变量中。有(便携式)方法可以做到这一点吗?

automake autoconf glade pkg-config autotools

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

检测合成器是否正在运行

我希望我的 UI 根据屏幕是否合成(从而支持某些效果)来更改设计。是否有可能

  • 可靠地查询 X 服务器是否正在运行合成窗口管理器
  • 打开/关闭合成时收到通知吗?

解决方案:

为了向不太熟悉 X11 API 的人详细说明 Andrey Sidorov 的正确答案,这是用于检测符合 EWMH 的合成器的代码:

int has_compositor(Display *dpy, int screen) {
    char prop_name[20];
    snprintf(prop_name, 20, "_NET_WM_CM_S%d", screen);
    Atom prop_atom = XInternAtom(dpy, prop_name, False);
    return XGetSelectionOwner(dpy, prop_atom) != None;
}
Run Code Online (Sandbox Code Playgroud)

x11 xlib

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

转发函数指针

我很惊讶地发现,显然std::forward不能与任意类型一起使用,尽管文档表明这一点.

#include <utility>

template<typename T>
void bar(T&&);

template<typename T>
void foo(T&& v) {
    bar(std::forward(v));
}

int main() {
    foo(main);
}
Run Code Online (Sandbox Code Playgroud)

产生

forward.cc: In instantiation of 'void foo(T&&) [with T = int (&)()]':
forward.cc:12:13:   required from here
forward.cc:8:23: error: no matching function for call to 'forward(int (&)())'
     bar(std::forward(v));
                       ^
forward.cc:8:23: note: candidates are:
In file included from /usr/include/c++/4.8.2/bits/stl_pair.h:59:0,
                 from /usr/include/c++/4.8.2/utility:70,
                 from forward.cc:1:
/usr/include/c++/4.8.2/bits/move.h:76:5: note: template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_From>::type&)
     forward(typename std::remove_reference<_Tp>::type& __t) noexcept
     ^
/usr/include/c++/4.8.2/bits/move.h:76:5: note:   template argument …
Run Code Online (Sandbox Code Playgroud)

c++ gcc g++ c++11

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