小编o_o*_*tle的帖子

为什么类可以轻松复制所有私有特殊成员函数?

代码如下:

#include <iostream>
#include <type_traits>

class A
{
    A() = default;
    A(const A&) = default;
    A(A&&) = default;
    A& operator=(const A&) = default;
    A& operator=(A&&) = default;
    ~A() = default;
    int a;
};

int main()
{
    std::cout << std::boolalpha <<
        std::is_trivially_copy_assignable_v<A> << " " <<
        std::is_trivially_copy_constructible_v<A> << " " <<
        std::is_trivially_move_assignable_v<A> << " " <<
        std::is_trivially_move_constructible_v<A> << " " <<
        std::is_trivially_destructible_v<A> << " " <<
        std::is_trivially_copyable_v<A> << "\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

And the output is false false false false false …

c++ language-lawyer c++20 trivially-copyable

14
推荐指数
2
解决办法
1357
查看次数

这是 C++ 中未定义的行为吗?

此示例是从cppreference复制的。

struct Y { int z; };
alignas(Y) std::byte s[sizeof(Y)];
Y* q = new(&s) Y{2};
const int f = reinterpret_cast<Y*>(&s)->z; // Class member access is undefined
                                           // behavior: reinterpret_cast<Y*>(&s)
                                           // has value "pointer to s" and does
                                           // not point to a Y object
const int g = q->z; // OK
const int h = std::launder(reinterpret_cast<Y*>(&s))->z; // OK
Run Code Online (Sandbox Code Playgroud)

我想知道像s[0] = std::byte{0}上面的语句之后添加操作是否是未定义的行为?看起来它并没有违反严格的别名规则,因为std::byte根据cppreference可以是任何类型的“AliasedType” ,这意味着将任何对象视为字节数组是合法的。

请注意,我添加了 c++20 标签,因为它们可能只有在 C++20 之后才被明确定义。

c++ strict-aliasing language-lawyer c++20

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

为什么使用 C++ 容器“数组”而不是传统的 C 数组?

流行的观点是 C++ 数组更安全,效率几乎相同。除了检查索引是否超出范围和不允许隐式类型转换为指针之外,还有其他功能吗?

此外,为什么传统 C 数组的隐式类型转换被认为是一种糟糕的方式?

我不太擅长 C++(也擅长英语),如果这个问题不值得回答,请原谅我。谢谢!

c++ containers stl c++11

4
推荐指数
1
解决办法
103
查看次数

为什么正则表达式 ^(?:a+)+$ 会导致灾难性的回溯?

我正在学习编译器原理(其正则表达式始终可以执行 中的任务O(n))和通用正则表达式。我注意到某些正则表达式可能会出现灾难性的回溯,这似乎与理论相冲突。

理论上,^(?:a+)+$可以转化为 NFA,如下所示:

全国期货协会

通过算法,可以将其转化为具有精确状态为 的 DFA a+。但在现实生活中,这会导致例如灾难性的回溯aaaaaab。为什么正则表达式不能编译成高效的DFA?或者一般来说,由组成的正则表达式|,*,+,(?:)应该相当于某种非回溯的DFA,顶多O(n^2)是从每一个可能的字符开始,每次都失败,但是为什么会像指数复杂度呢?编译器原理上的正则表达式和程序中使用的一般正则表达式有什么区别吗?

regex algorithm

4
推荐指数
1
解决办法
113
查看次数

为什么 C++ 标准引入了更多的输出方法而没有相应的输入方法?

C++20 引入<format>(C++23 很快引入<print>)。我喜欢这些方法,并且我总是尝试在支持时使用std::format它,而不是使用一系列<<.

但我注意到这种演变似乎只出现在输出中。为什么没有<scan>输入法之类的东西?

c++ io c++20

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

何时使用reinterpret_cast而不违反严格的别名规则?

很长一段时间我都是reinterpret_cast这样使用的:

static_assert(sizeof(int) == sizeof(float));
int a = 1;
float b = *reinterpret_cast<float*>(&a); // viewed as float in binary.
Run Code Online (Sandbox Code Playgroud)

然而,当我最近回顾C++中的类型转换时,我发现当考虑严格的别名规则时,它是UB!可以优化对初始数据的不同类型(或者确切地说,非相似类型)的指针的引用。(我知道std::bit_cast在 C++20 中这是另一种方法。)

从我的角度来看,reinterpret_cast主要是用于指针类型转换。然而,考虑到禁止取消引用,我如何使用另一种类型的指针?

我浏览了何时使用reinterpret_cast,下面引用了一个答案:

需要reinterpret_cast 的一种情况是与不透明数据类型交互时。这种情况经常发生在程序员无法控制的供应商 API 中。下面是一个人为的示例,其中供应商提供了用于存储和检索任意全局数据的 API。

但是当涉及到这些API的实现时,如果要在那里使用数据,就很难避免取消对指针的引用。

看起来只有转换为另一种指针类型并返回初始指针类型才是合理的(但这有什么意义?为什么不使用初始类型或直接定义模板?)。所以我的问题是:什么时候使用reinterpret_cast而不违反该规则?有没有通用的用法?

我真的是 C++ 的新手,所以任何建议将不胜感激。

c++ casting reinterpret-cast

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

为什么这里的 std::cmatch 比 std::smatch 慢?

我首先生成一个长随机字符串:

const int length = 100000;
std::uniform_int_distribution<int> distribution(0, 2);
std::default_random_engine engine{1}; // set 1 as seed

// Just for test usage, not optimal. 
for(int i = 0; i < length; i++) // random abc
    a.push_back('a' + distribution(engine));
std::regex r{ "abc" };
Run Code Online (Sandbox Code Playgroud)

然后我分别使用std::smatchstd::cmatch并对它们进行基准测试:

std::smatch m;
std::string a0 = a;
int result = 0; // to disable optimization.

while (std::regex_search(a0, m, r))
{
    a0 = m.suffix();
    result += static_cast<int>(a0[0]);
}
return result;
Run Code Online (Sandbox Code Playgroud)
std::cmatch m;
const char* currBegin = …
Run Code Online (Sandbox Code Playgroud)

c++ matching c++11

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