如果我从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_cast的a到Dog * d,但我们从来不使用d,除非我们确定它的一个Dog.
假设a不是a Dog,那么在演员阵容中这个未定义的行为是什么?或者它被定义为我们实际上没有使用,d除非它真的是一个Dog?
赞赏参考标准的相关部分.
(是的,我知道我可以使用dynamic_cast和RTTI,可能这不是很好的代码,但我对这是否有效更感兴趣)
在 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那么执行 …
请考虑以下代码:
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版本的参考?[当它是成员变量,静态或全局时,本地人无关紧要,因为它们超出范围]
*可能"交换和返回"比"复制,清除和返回"更好.
#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
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)
我有一个解决方案(在常量后面和减法之前添加一个空格),所以我主要想知道为什么?这与认为这里有指数有关吗?
我们有一些旧代码,我们正在更新它们以使用更现代的 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?
如果我有一段简单的代码,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 …