小编PBS*_*PBS的帖子

为什么这个struct padding技巧有效?

考虑这个简单的程序

#include <iostream>

struct A
{
    int   x1234;
    short x56;
    char  x7;
};

struct B : A
{
    char x8;
};

int main()
{
    std::cout << sizeof(A) << ' ' << sizeof(B) << '\n';
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这打印8 12.即使B可以在不破坏对齐要求的情况下打包成8个字节,但它却占用了贪婪的12个字节.

这样会很好sizeof(B) == 8,但答案是结构的大小是否必须 是该结构对齐的精确倍数?表明没有办法.

因此,当以下时我感到惊讶

struct MakePackable
{
};

struct A : MakePackable
{
    int   x1234;
    short x56;
    char  x7;
};

struct B : A
{
    char x8;
};
Run Code Online (Sandbox Code Playgroud)

印刷8 8 …

c++ inheritance padding

28
推荐指数
1
解决办法
426
查看次数

可以使用C++中的严格别名来模拟C的restrict关键字吗?

问题

restrictC++中缺少C中的关键字,所以出于兴趣,我一直在寻找一种在C++中模拟相同功能的方法.

具体来说,我希望以下内容相同:

// C
void func(S *restrict a, S *restrict b)

// C++
void func(noalias<S, 1> a, noalias<S, 2> b)
Run Code Online (Sandbox Code Playgroud)

哪里 noalias<T, n>

  • 表现就像T*->和访问时一样*
  • 可以从a构造T*(这样函数可以被称为func(t1, t2),where t1t2are都是类型T*)
  • 索引n指定变量的"混叠类",使类型的变量noalias<T, n>noalias<T, m>可从未假定为别名对于n!=米.

尝试

这是我的严重缺陷解决方案:

template <typename T, int n>
class noalias
{
    struct T2 : T {};
    T *t;

public:
    noalias(T *t_) : t(t_) {}
    T2 *operator->() const {return static_cast<T2*>(t);} …
Run Code Online (Sandbox Code Playgroud)

c++ restrict strict-aliasing c++14

22
推荐指数
1
解决办法
882
查看次数

将unique_ptr添加到向量中的类会导致3倍的加速

背景

我有一个大图(100k节点),其中每个节点必须存储每个传出边的一些信息.std::vector<bool>我没有将其保留在一个中,而是使用dynamic_bitsetBoost 1.58来执行按位操作.每个节点还保持指向某个多态对象的指针.一个最小的例子看起来像这样,

struct Node
{
    std::vector<size_t>     succ;
    boost::dynamic_bitset<> succ_flags;
    std::unique_ptr<Object> data;
};
Run Code Online (Sandbox Code Playgroud)

问题

考虑这个简单的基准程序,它创建并销毁图表:

#include <vector>
#include <boost/dynamic_bitset.hpp>
#include <memory>

constexpr int N = 50000;

struct Node
{
    std::vector<size_t>     succ;
    boost::dynamic_bitset<> succ_flags;
  //std::unique_ptr<int>    data;

    Node(int i)
    {
        for (int j = i; j < N; j += i) succ.emplace_back(j);
        succ_flags.resize(succ.size());
    }
};

int main()
{
    std::vector<Node> nodes;
    for (int i = 1; i <= N; i++) nodes.emplace_back(i);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

time命令下运行,典型的结果是

real    0m0.055s …
Run Code Online (Sandbox Code Playgroud)

c++ boost vector c++11

17
推荐指数
1
解决办法
518
查看次数

C++标准强制要求局部变量的引用是低效的吗?

我最近需要一个通过引用捕获多个局部变量的lambda,所以我制作了一个测试片段来研究它的效率,并-O3使用clang 3.6 编译它:

void do_something_with(void*);

void test()
{
    int a = 0, b = 0, c = 0;

    auto func = [&] () {
        a++;
        b++;
        c++;
    };

    do_something_with((void*)&func);
}
Run Code Online (Sandbox Code Playgroud)
movl   $0x0,0x24(%rsp)
movl   $0x0,0x20(%rsp)
movl   $0x0,0x1c(%rsp)

lea    0x24(%rsp),%rax
mov    %rax,(%rsp)
lea    0x20(%rsp),%rax
mov    %rax,0x8(%rsp)
lea    0x1c(%rsp),%rax
mov    %rax,0x10(%rsp)

lea    (%rsp),%rdi
callq  ...
Run Code Online (Sandbox Code Playgroud)

显然,lambda只需要一个变量的地址,所有其他变量都可以通过相对寻址来获得.

相反,编译器在堆栈上创建了一个包含指向每个局部变量的指针的结构,然后将结构的地址传递给lambda.这和我写的一样:

int a = 0, b = 0, c = 0;

struct X
{
    int *pa, *pb, *pc;
};

X x = {&a, …
Run Code Online (Sandbox Code Playgroud)

c++ lambda compiler-optimization language-lawyer

11
推荐指数
1
解决办法
462
查看次数

为什么vtable不能包含重复的函数?

想象一个项目,其中有一个如下所示的接口类:

struct Interface
{
    virtual void f()=0;
    virtual void g()=0;
    virtual void h()=0;
};
Run Code Online (Sandbox Code Playgroud)

假设其他地方,有人希望创建一个类实现这个接口,为此f,g,h都做同样的事情.

struct S : Interface
{
    virtual void f() {}
    virtual void g() {f();}
    virtual void h() {f();}
};
Run Code Online (Sandbox Code Playgroud)

然后,它会生成一个虚函数表的有效优化S其条目都指向S::f,从而节省的包装函数的调用gh.

但是,打印vtable的内容表明不执行此优化:

S s;
void **vtable = *(void***)(&s);  /* I'm sorry. */
for (int i = 0; i < 3; i++)
    std::cout << vtable[i] << '\n';
Run Code Online (Sandbox Code Playgroud)

0x400940
0x400950
0x400970

与clang和gcc之间的切换一样编译-O3-Os …

c++ vtable compiler-optimization

6
推荐指数
1
解决办法
178
查看次数

编码风格绝对可以保证没有内存泄漏吗?

从不使用

new
delete
release

并且更喜欢使用

std::make_unique
std::unique_ptr
std::move
reset (冗余)

应该在道德上导致没有内存泄漏:新的指针只能在智能指针内部创建,因为我们不允许使用它们release.

因此,人们可能会试图使用这种编码风格,然后再也不用费心去检查内存泄漏 - 无论在哪里抛出异常,智能指针的RAII语义都应该在堆栈解开时清理任何悬空指针.

除了C++之外,还有很多令人讨厌的惊喜.根据我的假设反复粉碎的经验,我不禁想到可能会有一些角落案件无论如何都会导致内存泄漏.更糟糕的是,可能有一种明显的方式来释放指针的所有权而不是release自身.或其它智能指针类没有一个explicit构造函数可能会意外地摄取通过获得的原始指针get,导致双重的FreeS ...


有漏洞吗?如果有,可以通过添加一些更简单的限制来修复它们吗?(不分配任何内存不算数!)如果可以达到一组防止所有类型的内存错误的编码指南,那么完全忘记内存管理的细节是否可以?

c++ memory-leaks coding-style c++14

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