小编gez*_*eza的帖子

是否允许使用具有相同整数值的枚举专门化模板?

看看这个简单的片段:

enum class Enum1 { Value };
enum class Enum2 { Value };
template <auto> struct Foo;
template <> struct Foo<Enum1::Value> { };
template <> struct Foo<Enum2::Value> { };
Run Code Online (Sandbox Code Playgroud)

Clang编译了这个,但是gcc-7.2失败了:

x.cpp:5:20:错误:重新定义'struct Foo <(Enum1)0>'template <> struct Foo {};

此错误消息似乎无效,如第5行所示Enum2::Value.

哪个编译器正确?这是符合规范的代码吗?

c++ language-lawyer c++17

16
推荐指数
1
解决办法
391
查看次数

返回*&object时是否允许复制/移动省略?

看看这段代码:

#include <stdio.h>

struct Foo {
    Foo() { }
    Foo(const Foo &) { printf("copy\n"); }
    Foo(Foo &&) { printf("move\n"); }
};

Foo getFoo() {
    Foo f;
    return *&f;
}

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

C++ 14标准说(12.8/31)允许复制/移动省略:

在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cv- unquali fi ed类型的非易失性自动对象(函数或catch子句参数除外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作

在我的例子中,返回表达式不是名称,所以我认为不允许使用elision.

我检查了GCC/clang/MSVC,虽然clang/MSVC没有删除副本,但是GCC会这样做.GCC是否违反了此标准?

c++ language-lawyer

15
推荐指数
1
解决办法
344
查看次数

15
推荐指数
1
解决办法
417
查看次数

使用new char []或malloc的结果来表示浮动*是UB(严格别名冲突)吗?

哪些代码有UB(具体来说,哪些违反了严格的别名规则)?

void a() {
    std::vector<char> v(sizeof(float));
    float *f = reinterpret_cast<float *>(v.data());
    *f = 42;
}

void b() {
    char *a = new char[sizeof(float)];
    float *f = reinterpret_cast<float *>(a);
    *f = 42;
}

void c() {
    char *a = new char[sizeof(float)];
    float *f = new(a) float;
    *f = 42;
}

void d() {
    char *a = (char*)malloc(sizeof(float));
    float *f = reinterpret_cast<float *>(a);
    *f = 42;
}

void e() {
    char *a = (char*)operator new(sizeof(float));
    float *f = reinterpret_cast<float *>(a);
    *f = …
Run Code Online (Sandbox Code Playgroud)

c++ malloc strict-aliasing object-lifetime language-lawyer

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

放置new的返回值与其操作数的转换值之间是否存在(语义)差异?

放置new的返回值与其操作数的转换值之间是否存在(语义)差异?

struct Foo { ... };
char buffer[...];

Foo *a = new(buffer) Foo;
Foo *b = reinterpret_cast<Foo *>(buffer);
Run Code Online (Sandbox Code Playgroud)

是否ab以某种方式有什么不同?


编辑:根据DaBler的评论,这个问题告诉我,如果使用const/reference成员则存在差异:使用const成员放置新类和赋值

所以,我的小位的更新问题:是否ab以任何方式不同,如果Foo没有const或引用成员?

c++ strict-aliasing placement-new language-lawyer reinterpret-cast

13
推荐指数
2
解决办法
488
查看次数

为什么编译器不优化这个呢?

看看这段代码:

struct Data {
};

struct Init {
    Data *m_data;

    Init() : m_data(new Data) { }
    ~Init() {
        delete m_data;
    }
};

class Object {
    private:
        const int m_initType;
        Data *m_data;
    public:
        Object(const Init &init) : m_initType(0), m_data(init.m_data) { }
        Object(Init &&init) : m_initType(1), m_data(init.m_data) { init.m_data = nullptr; }
        ~Object() {
            if (m_initType==1) {
                delete m_data;
            }
        }
};

void somefunction(const Object &object); // it is intentionally not defined

void callInitA() {
        Init x;
        somefunction(x);
}

void callInitB() { …
Run Code Online (Sandbox Code Playgroud)

c++ gcc clang

12
推荐指数
1
解决办法
483
查看次数

为什么32字节的循环对齐使代码更快?

看看这段代码:

one.cpp:

bool test(int a, int b, int c, int d);

int main() {
        volatile int va = 1;
        volatile int vb = 2;
        volatile int vc = 3;
        volatile int vd = 4;

        int a = va;
        int b = vb;
        int c = vc;
        int d = vd;

        int s = 0;
        __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop");
        __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop");
        __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop");
        __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop");
        for (int i=0; i<2000000000; i++) {
                s += test(a, b, …
Run Code Online (Sandbox Code Playgroud)

performance benchmarking gcc x86-64 clang

12
推荐指数
1
解决办法
735
查看次数

添加到"char*"指针UB,当它实际上没有指向char数组?

C++ 17(expr.add/4)说:

当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型.如果表达式P指向具有n个元素的数组对象x的元素x [i],则表达式P + J和J + P(其中J具有值j)指向(可能是假设的)元素x [i + j]如果0≤i+j≤n; 否则,行为未定义.同样地,如果0≤i-j≤n,则表达式P-J指向(可能是假设的)元素x [i-j]; 否则,行为未定义.

struct Foo {
    float x, y, z;
};

Foo f;
char *p = reinterpret_cast<char*>(&f) + offsetof(Foo, z); // (*)
*reinterpret_cast<float*>(p) = 42.0f;
Run Code Online (Sandbox Code Playgroud)

该行标有(*)UB?reinterpret_cast<char*>(&f)不指向char数组,而是指向浮点数,因此根据引用的段落它应该是UB.但是,如果它是UB,那么它offsetof的用处将是有限的.

是UB吗?如果没有,为什么不呢?

c++ language-lawyer

12
推荐指数
3
解决办法
392
查看次数

可以使用std :: launder将对象指针转换为其封闭的数组指针吗?

目前的标准草案(可能是C++ 17)在[basic.compound/4]中说:

[注意:数组对象及其第一个元素不是指针可互换的,即使它们具有相同的地址. - 结束说明]

因此,指向对象的指针不能reinterpret_cast获得其封闭的数组指针.

现在,有std::launder,[ptr.launder/1]:

template<class T> [[nodiscard]] constexpr T* launder(T* p) noexcept;

要求:p表示内存中字节的地址A. 在其生命周期内且其类型类似于T的对象X位于地址A处.可通过结果到达的所有存储字节都可通过p(见下文)到达.

和的definion 可达是在[ptr.launder/3] :

备注:只要可以在核心常量表达式中使用其参数的值,就可以在核心常量表达式中使用此函数的调用.如果对象Y位于Y所占用的存储区内,则指向存储的字节可以到达,如果Y是指针可互换的对象,则指向对象Y,或者如果Y是数组元素,则指向立即封闭的数组对象.如果T是函数类型或cv void,则程序格式错误.

现在,乍一看,似乎std::launder可以用来做上述转换,因为我强调的部分.

但.如果p指向数组的对象,则根据此定义可以访问数组的字节(即使p不是指针可互换为数组指针),就像清洗的结果一样.因此,该定义似乎没有说明这个问题.

那么,可以std::launder用来将对象指针转换为其封闭的数组指针吗?

c++ language-lawyer c++17

12
推荐指数
1
解决办法
576
查看次数

Is converting a reinterpret_cast'd derived class pointer to base class pointer undefined behavior?

Have a look at is simple example:

struct Base { /* some virtual functions here */ };
struct A: Base { /* members, overridden virtual functions */ };
struct B: Base { /* members, overridden virtual functions */ };

void fn() {
    A a;
    Base *base = &a;
    B *b = reinterpret_cast<B *>(base);
    Base *x = b;
    // use x here, call virtual functions on it
}
Run Code Online (Sandbox Code Playgroud)

Does this little snippet have Undefined Behavior?

reinterpret_cast定义明确,它返回的值不变base,只是类型为B …

c++ language-lawyer

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