小编Jan*_*tke的帖子

为什么静态成员函数在重载解析期间被视为具有隐式对象参数?

在此链接中: 隐式对象参数

在这句话中:

如果任何候选函数是不具有显式对象参数 (C++23 起) 的成员函数(静态或非静态),但不是构造函数,则将其视为具有额外参数(隐式对象参数) ) 表示调用它们的对象,并出现在第一个实际参数之前。

我不明白为什么这里提到静态这个词?隐式对象参数不是指针this(仅存在于非静态函数中)吗?

在此链接中编辑:链接

引用 :

关键字 this 是右值 (C++11 之前) 纯右值 (C++11 起) 表达式,其值是隐式对象参数(调用非静态成员函数的对象)的地址。它可以出现在以下环境中:

c++ member-functions language-lawyer overload-resolution

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

类型特征的 _t 别名和 _v 变量模板的目的是什么?

很多*_v后缀*_t,例如std::is_same_vstd::invoke_result_t和数result_of_t以百万计的其他此类函数。

它们为什么存在?std::result_of::type在任何情况下公开诸如或 之类的实现细节是否有益std::is_same::value?忽略标准合规性,_v _t版本是否应该始终是首选?难道这些::type ::value版本根本就不存在吗?

c++ language-design type-traits c++14 c++17

16
推荐指数
4
解决办法
1762
查看次数

在 C++ 中传递 va_list 作为对函数的引用是否合法?

在代码审查/clang-tidy 运行时,我遇到了一个具有如下签名的函数:

void appendFoo(const char * fmt, va_list& rVaList);
Run Code Online (Sandbox Code Playgroud)

我以前从未见过这个。Afaik,您可以va_list按值传递(也可以通过指针传递?)。

这引出了我的第一个问题:通过va_list引用传递合法吗?它是否按预期工作?

不管怎样,appendFoo()调用vsprintf()它的定义和 clang-tidy 给出了以下警告:Function 'vsprintf' is called with an uninitialized va_list argument [clang-analyzer-valist.Uninitialized]。看起来的定义appendFoo()基本上是这样的:

void appendFoo(const char * fmt, va_list& rVaList) {
  // retracted: allocate buffer

  vsprintf(buffer, fmt, rVaList);

  // errorhandling
  // de-allocate buffer
}
Run Code Online (Sandbox Code Playgroud)

(是的, 的返回值vsprintf被忽略,错误以另一种方式“处理”。我正在修复它......)

特别是,不va_copy调用va_start、 等。

删除引用va_list并按值传递,即将签名更改为void appendFoo(const char * fmt, va_list rVaList);,消除了 clang-tidy 警告。 …

c++ pass-by-reference variadic-functions

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

C++17 中 std::byte 只能按位运算?

CPP 参考文献中指出:

std::byte是一种独特的类型,它实现了 C++ 语言定义中指定的字节概念。

与 char 和 unsigned char 一样,它可用于访问其他对象(对象表示)占用的原始内存,但与这些类型不同的是,它不是字符类型,也不是算术类型。字节只是位的集合,并且只为其定义了按位运算符

但这不是真的:因为它是枚举类型,所以比较操作(<, <=, >, >=, ==, !=)也是可能的。

这是故意的吗,例如std::byte也用作 等的密钥std::map

c++ byte language-lawyer std-byte

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

为什么 std::sleep_for(std::chrono::hours::max()) 在 Linux 上立即返回?

我正在运行一个提供服务的 C++ 程序,并注意到即使不提供任何请求,它也会占用 100% 的 CPU。我将问题缩小到一个 while 循环,该循环调用std::sleep_for以防止服务退出。

为了测试,我编译并运行了这个简单的测试程序:

#include <chrono>
#include <thread>

int main(int argc, char * argv[])
{
    std::this_thread::sleep_for(std::chrono::hours::max());
}
Run Code Online (Sandbox Code Playgroud)

我的预期是它会休眠很长时间,事实上,当我在 M1 Mac 上尝试它时,我看到了预期的行为。然而,当我在 Redhat Linux 8 机器上运行它时,它立即返回。我还在 Mac 上运行的 Rocky Linux 8 docker 容器上进行了尝试,这也立即返回。这证实了这种情况通常发生在 RHEL 8 系统上 - 或者至少在 gcc 8.5.0 上发生,因为两个 Linux 系统上的编译器版本是相同的(Mac 上的编译器是 Apple 提供的 clang)。

这解释了为什么我的服务占用了 100% 的 CPU,因为它是在 while 循环中调用的。但我从未听说过这种行为。还有其他人吗?

当然,我可以通过睡一会儿来轻松解决问题std::chrono::seconds(1)。我只是出于求知欲才问这个问题。

c++ linux multithreading compiler-bug c++-chrono

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

如何在成员函数内完美转发`*this`对象

是否可以*this在成员函数内完美转发对象?如果是的话,我们该怎么做呢?如果不是,那么为什么不呢?我们有哪些替代方案可以达到同样的效果。

请参阅下面的代码片段以更好地理解该问题。

class Experiment {
public:
  double i, j;
  Experiment(double p_i = 0, double p_j = 0) : i(p_i), j(p_j) {}

  double sum() { return i + j + someConstant(); }

  double someConstant() && { return 10; }

  double someConstant() & { return 100; }
};

int main() {
  Experiment E(3, 5);
  std::cout << std::move(E).sum() << "\n";  // prints: 108
  std::cout << E.sum() << "\n";             // prints: 108
}
Run Code Online (Sandbox Code Playgroud)

如果我们认为*this成员函数内的对象double sum()始终是左值或x值(因此是左值),则此输出似乎是预期的。请确认这是否属实。

如何才能完美地将*this对象转发给成员函数 …

c++ overload-resolution c++11 explicit-object-parameter

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

为什么使用 constexpr 时超出范围变量的地址等于 0?

关于语义,我有些不明白constexprx当然,在堆栈上分配的地址无法在编译时计算出来。

constexpr auto foo()
{
    int x = 5;    
    return &x;
}

static_assert(foo() == 0);
Run Code Online (Sandbox Code Playgroud)

尽管如此,这段代码仍然可以编译(GCC 13.2 -std=c++20),并且 的地址x等于0,这可以在通过的声明中看到static_assert

请参阅https://godbolt.org/z/Pjrx3cb68

c++ gcc constexpr

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

为什么编译器不能优化 try-catch 块中的单个 throw 语句?

我只是在编译器资源管理器中玩一些 C++ 代码,并在编译简单的try/catch块时注意到一些意外的行为。以下两个片段都是使用 gcc 使用优化标志编译的-O3实时示例)。

在第一个程序中,整个try/catch块被删除,因为行为上没有明显的差异,从而产生与return 0;. 这正是我期望编译器产生的结果。

int main() {
    try {
        int x{ 10 };
    }
    catch (...) {
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)
main:
        xor     eax, eax
        ret
Run Code Online (Sandbox Code Playgroud)

在第二个片段中,我有throw一个例外,而不是仅仅初始化一个int. 抛出该异常后,我将继续使用catch-all 处理程序,该处理程序是空的。之后就只有return 0;声明了。这意味着该程序的可观察行为将与第一个程序相同。然而,大会表明,整个事情仍在try继续catch

int main() {
    try {
        throw 10;
    }
    catch (...) {
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)
main:
        push    rcx
        mov …
Run Code Online (Sandbox Code Playgroud)

c++ error-handling exception try-catch compiler-optimization

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

为什么我特别应该将 std::span 而不是 std::vector&amp; 传递给函数?

我知道这可能与问题重叠:什么是 \xe2\x80\x9cspan\xe2\x80\x9d 以及我何时应该使用它?,但我认为问题的这个特定部分的答案相当令人困惑。一方面,有这样的引用:

\n
\n

如果您有一个标准库容器(或 Boost 容器等),并且您知道它最适合您的代码,请不要使用它。它无意取代其中任何一个。

\n
\n

但在同一个答案中,出现了这样的说法:

\n
\n

当您希望数据在内存中连续时,是将 const vector& 传递给函数的合理替代方案。再也不用被 C++ 大师骂了!

\n
\n

那么我没有到达哪一部分呢?我什么时候会这样做:

\n
void foo(const std::vector<int>& vec) {}\n
Run Code Online (Sandbox Code Playgroud)\n

而这是什么时候呢?

\n
void foo(std::span<int> sp) {}\n
Run Code Online (Sandbox Code Playgroud)\n

还有,这会不会

\n
void foo(const std::span<int> sp) {}\n
Run Code Online (Sandbox Code Playgroud)\n

有什么意义吗?我认为不应该,因为 astd::span只是 a struct,包含指针和长度。但是,如果它不能阻止您更改std::vector作为参数传递的值,那么它如何替换const std::vector<T>&

\n

c++ vector c++20 std-span

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

thread_local + std::thread 销毁时死锁

有谁知道这是什么类型的UB吗?使用 MSVC 19.29.30148 构建时,以下代码在jthread销毁时死锁,有时在 std::cout 之后死锁,有时在之前死锁。这在某种程度上与 thread_local 有关,但我看不出问题是什么。它似乎在其他编译器和平台下工作得很好。

#include <thread>
#include <memory>
#include <iostream>

int main(void)
{
    std::thread t2(
        [&] {
            thread_local std::jthread asd([] {
                    std::cout << "ASD" << std::endl;
                    });
        });
    if (t2.joinable()) { t2.join(); }
}
Run Code Online (Sandbox Code Playgroud)

更新:在静态和动态运行时均可重现

c++ multithreading msvcrt compiler-bug c++20

13
推荐指数
0
解决办法
362
查看次数