小编Mik*_*ine的帖子

错误的演员表 - 是演员表或使用未定义的行为

如果我从Base转换为Derived类型,但Base类型不是派生类型的实例,但只使用结果,是否会得到未定义的行为?

很难理解我在问什么?看看这个例子:

struct Animal { int GetType(){...} };
struct Dog : Animal { bool HasLoudBark(){...}};
struct Cat : Animal { bool HasEvilStare(){...} };

Animal * a = ...;
Dog* d = static_cast<Dog*>(a);

if(a->GetType() == DogType && d->HasLoudBark())
    ....
Run Code Online (Sandbox Code Playgroud)

在这种情况下a可能或不是Dog.我们总是做static_castaDog * d,但我们从来不使用d,除非我们确定它的一个Dog.

假设a不是a Dog,那么在演员阵容中这个未定义的行为是什么?或者它被定义为我们实际上没有使用,d除非它真的是一个Dog

赞赏参考标准的相关部分.

(是的,我知道我可以使用dynamic_cast和RTTI,可能这不是很好的代码,但我对这是否有效更感兴趣)

c++ casting undefined-behavior language-lawyer

36
推荐指数
2
解决办法
2037
查看次数

在 lambda 中捕获 `thread_local`

在 lambda 中捕获 thread_local:

#include <iostream>
#include <thread>
#include <string>

struct Person
{
    std::string name;
};

int main()
{
    thread_local Person user{"mike"};
    Person& referenceToUser = user;

    // Works fine - Prints "Hello mike"
    std::thread([&]() {std::cout << "Hello " << referenceToUser.name << std::endl;}).join();

    // Doesn't work - Prints "Hello"
    std::thread([&]() {std::cout << "Hello " << user.name << std::endl;}).join();

    // Works fine - Prints "Hello mike"
    std::thread([&user=user]() {std::cout << "Hello " << user.name << std::endl;}).join();
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/zeocG5ohb

看起来如果我使用 a 的原始名称,thread_local那么执行 …

c++ language-lawyer thread-local-storage c++11 stdthread

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

移动的shared_ptr是否保证被清空?

请考虑以下代码:

struct Bar
{
    std::shared_ptr<int> MemberFunction()
    {
        return std::move(m_memberVariable);
    }

    std::shared_ptr<int> m_memberVariable;
};
Run Code Online (Sandbox Code Playgroud)

是否保证std::movefrom a shared_ptr<T>将实际删除成员变量中的引用?或者我应该复制,清除并返回副本以保证*

显然,在的情况下,unique_ptr<T>它确实是正确的(它也不可能这样做),但不标准的保证,一个std::move从d shared_ptr版本的参考?[当它是成员变量,静态全局时,本地人无关紧要,因为它们超出范围]

*可能"交换和返回"比"复制,清除和返回"更好.

c++ move shared-ptr c++11

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

为什么函数参数类型上的enable_if会影响重载解析?

请参阅 godbolt 上的代码

#include <iostream>
#include <cmath>
#include <type_traits>

template <typename T>
void f(T, T) // 1
{
    std::cout << "Primary\n";
}

template <typename T>
void f(T, std::enable_if_t<std::is_floating_point_v<T>, T>) // 2
{
    std::cout << "Special\n";
}

/*template <typename T>
std::enable_if_t<std::is_floating_point_v<T>> f(T, T) // 3
{
    std::cout << "Special\n";
}*/

int main()
{
    f(1.1, 1.1); // prints 'Primary'
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,std::enable_if应用于第二个函数模板重载的函数类型。该函数是通过 [T = double] 推导来调用的,并且它调用重载 1。但是,如果我注释掉重载 2 并将其替换为重载 3,那么编译器会抱怨该调用不明确。我也期望在第一种情况下,为什么编译器更喜欢重载 1 而不是 2?

我阅读了“函数模板重载”部分,但对我来说,重载 2 看起来更专业。

c++ language-lawyer enable-if function-templates-overloading

14
推荐指数
0
解决办法
77
查看次数

当以“E”结尾时,减去十六进制常量时出错

int main()
{
    0xD-0; // Fine
    0xE-0; // Fails
}
Run Code Online (Sandbox Code Playgroud)

第二行无法在 clang 和 gcc 上编译。任何其他十六进制常量结尾都可以(0-9、AD、F)。

错误:

<source>:4:5: error: unable to find numeric literal operator 'operator""-0'
    4 |     0xE-0;
      |     ^~~~~
Run Code Online (Sandbox Code Playgroud)

我有一个解决方案(在常量后面和减法之前添加一个空格),所以我主要想知道为什么?这与认为这里有指数有关吗?

https://godbolt.org/z/MhGT33PYP

c++ language-lawyer

9
推荐指数
1
解决办法
181
查看次数

原子地访问不是 `std::atomic` 的变量

我们有一些旧代码,我们正在更新它们以使用更现代的 C++。它以前依赖于(令人讨厌的)Visual Studio 扩展来volatile原子地访问变量。

该功能类似于

T ReadAq(T* val)
{
    return *(volatile T*)val;
}
Run Code Online (Sandbox Code Playgroud)

请注意,它T已适当对齐且足够小,以便我们支持的架构本身能够在不撕裂的情况下进行单次读取。

写入变量有类似的功能,并且变量的所有使用都通过这些函数之一。

我真的不想更改它的签名(因为这对所有调用者来说都是一个巨大的改变),所以我希望能够执行以下操作:

T ReadAq(T* val)
{
    return std::atomic_read(val, std::memory_order_acquire);
}
Run Code Online (Sandbox Code Playgroud)

但标准中似乎不存在这样的功能 - 所有原子操作都在 std::atomic 类型上。关于是否可以在不更改签名的情况下解决此问题有什么想法吗ReadAq

c++ atomic

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

选择退出严格别名规则的“char”豁免

如果我有一段简单的代码,uint32_t那么它可以比使用uint8_t. 据我所知,这是因为 char 可以豁免严格的别名规则。考虑:

using T = uint32_t;

T *a;
T *b;
T *c;

void mult(int num)
{
    for (int count = 0; count < num; count++)
    {
        a[count] = b[count] * c[count];
    }
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/sW1xnTrhc

这有一个内部循环-01

.LBB0_2:                                # =>This Inner Loop Header: Depth=1
        mov     r8d, dword ptr [rcx + 4*rdi]
        imul    r8d, dword ptr [rax + 4*rdi]
        mov     dword ptr [rdx + 4*rdi], r8d
        inc     rdi
        cmp     rsi, rdi
        jne     .LBB0_2
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,它只是加载一个值,进行乘法,存储结果,然后循环。这很好。但是,如果我使用uint8_t …

c++ types simd strict-aliasing compiler-optimization

5
推荐指数
0
解决办法
142
查看次数