标签: c++20

为什么 std::vector 和 std::string 使用“for”循环来复制或移动元素?

为什么 std::vector 和 std::string 使用“for”循环来复制或移动元素?这不会影响性能吗?

最近,我正在阅读llvm-libcxx中 libcxx 的 stl 源代码。但是我发现 std::vector 和 std::string 使用“for”循环来复制或移动容器中的元素。与元素为基本类型(例如 memcpy 和 memmove)时使用一些更快的函数进行处理相比,这是否会降低性能。这是 std::vector 中的代码

LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) {
    if (!__libcpp_is_constant_evaluated()) {
        _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
    }
    char_type* __r = __s1;
    for (; __n; --__n, ++__s1, ++__s2)
        assign(*__s1, *__s2);
    return __r;
}
Run Code Online (Sandbox Code Playgroud)

我想知道为什么不实现专门的版本向量或字符串来加速处理。最初,我认为编译器会优化这部分代码,但事实并非如此。我已经测试了 for 循环和memcpy(我知道这是由 SSE 或 AVX 指令加速)之间的性能。

这是测试代码:

void func(char *p1, char *p2, int len) {
    memcpy(p1, …
Run Code Online (Sandbox Code Playgroud)

c++ stl c++20

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

为什么 C++20 范围概念指定了明显误导性的要求?

我正在努力满足我的班级的 C++20 概念。

struct C1
{
    int* begin();
    int* end();
};

static_assert(std::ranges::range<C1>);  // Compiles fine

struct C2 {};

namespace std::ranges    // (A)
{
    auto begin(C2&);
    auto end(C2&);
}

static_assert(std::ranges::range<C2>);  // Fails to compile
Run Code Online (Sandbox Code Playgroud)

std::ranges::range<>概念定义如下:

template <class _Rng>
concept range = requires(_Rng& __r) {
  std::ranges::begin(__r);
  std::ranges::end(__r);
};
Run Code Online (Sandbox Code Playgroud)

从字面意思上看,它指示我声明上面的函数 (A)。但这些都没有帮助。另一方面,像在类中一样定义两个成员函数C1 确实有效。我的问题是,我只是看不到概念所强加的要求与有助于 class 的解决方案之间的语义联系C1。它告诉我做一件事,而实际上我需要做另一件事。

请对此提供一些解释。

背景:在我的生产代码中,我的类确实定义了一个begin()end()函数,每个函数返回一个迭代器。但这个range概念并不满足这些定义,也未能告诉我原因。

请参阅编译器资源管理器上的完整示例

c++ c++-concepts c++20 std-ranges

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

额外的 std::map::contains 调用与处理异常?

c++中什么效率更高?

if (my_map.contains(my_key)) return my_map.at(my_key);
Run Code Online (Sandbox Code Playgroud)

或者

try { return my_map.at(my_key); } catch (std::out_of_range e) { ... }
Run Code Online (Sandbox Code Playgroud)

c++ stl stdmap c++20

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

我们可以将“Eigen::Vector&lt;T, D + 1&gt;&amp; x”重新解释转换为“Eigen::Vector&lt;T, D&gt;&amp;”,以从“x”中提取第一个“D”分量吗?

我需要计算D维函数的函数值和梯度并将这些值加在一起。D我认为简单地将梯度部分存储在第一个分量中并将函数值存储在D+1维向量的最后一个分量中将是有益于计算的。

但是,如何从该维向量中提取第一个D分量(即梯度部分) ?D+1我知道可以选择切片,但我不想在这里添加任何无意义的开销。所以,我尝试简单地reinterpret_cast<Eigen::Vector<T, D>&>在我的上做一个Eigen::Vector<T, D + 1>并且它起作用了;但这真的能保证有效(并且安全)吗?

c++ reinterpret-cast eigen c++20

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

这个语句在 C++ 概念中意味着什么以及为什么它不起作用

我正在尝试 C++20 功能,并且我想用来concept限制模板仅传递具有名为 的成员List且其类型应该为 的类std::vector<int>。这是前言。

要在不使用 的情况下执行此操作concept,我将编写以下代码:

class RandomClass
{
public:
    std::vector<int> List;
};

typename std::enable_if<std::is_same<decltype(T::List), std::vector<int>>::value>::type
func(T& arg)
{
      ...
}

int main()
{
    auto randomObj= RandomClass();
    func(randomObj);
}
Run Code Online (Sandbox Code Playgroud)

我要求 New Bing 使用concept重写它,它给出了以下内容:

template<class T>
concept HasList = requires(T t) {
    { t.List } -> std::same_as<std::vector<int>>;
};

template<class T> requires HasList<T>
void func(T& arg)
Run Code Online (Sandbox Code Playgroud)

但是这段代码无法编译,编译器给出了'func': no matching overloaded function found.

然后我搜索std::same_as用法并尝试了这个:

template<class T>
concept HasList …
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++20

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

如何在全局级别定义 unordered_map?

我试图在全局级别定义两个无序映射,我用循环定义它们,并且我不想将循环放入main().

更具体地说,我试图定义一个基于 36 的字母表,我使用阿拉伯数字表示数字 0-9,然后使用基本拉丁字母表表示数字 10-35,一个映射用于将字符串转换为整数,并且它应该支持大写和小写,另一个用于将整数转换为给定基数的字符串表示形式,并且它只能是小写。

这是我的代码,显然它不起作用:

#include <unordered_map>

using namespace std;
const unordered_map<string, int> digits;
const unordered_map<int, string> alphabet;

for (int i = 0; i < 10; i++) {
    string d = char(i + 48);
    digits[d] = i;
    alphabet[i] = d;
}

for (int i = 10; i < 36; i++) {
    string upper = char(i + 55);
    string lower = char(i + 87);
    digits[upper] = i;
    digits[lower] = i;
    alphabet[i] = lower;
}
Run Code Online (Sandbox Code Playgroud)

我知道如果我将循环放入函数中main(),它应该可以工作。但我不想那样做。 …

c++ unordered-map global-variables c++20

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

C++ 是机器无关的还是机器相关的?

https://www.geeksforgeeks.org/introduction-to-c-programming-language/ \n在一些按键和功能下

\n
\n

机器独立但平台相关:C++ 可执行文件不是平台无关的(Linux 上编译的程序无法在 Windows 上运行\xe2\x80\x99),但它们是机器无关的。

\n
\n
    \n
  1. 平台无关:这部分语句正确指出 C++ 可执行文件不是平台无关的。由于系统库、系统调用和可执行文件格式的差异,在一种操作系统(例如 Linux)上编译的程序通常不会直接在另一种操作系统(例如 Windows)上运行。

    \n
  2. \n
  3. 机器独立:本文中的术语“机器独立”可能会产生误导或不精确。编译的 C++ 可执行文件也不是真正独立于机器的。它们是机器相关的,因为它们被编译为特定于目标 CPU 架构的机器代码。例如,为 x86 架构编译的代码将无法在基于 ARM 的计算机上运行。

    \n
  4. \n
\n

那么为什么在每一篇文章中都写到 C++ 是机器独立的呢?

\n

C++ 可执行文件既不独立于平台(它们依赖于操作系统),也不独立于机器(它们依赖于 CPU 架构)。它们特定于平台和机器。

\n

在实践中,如果你想在不同的平台或机器上运行 C++ 程序,通常需要针对每个特定的平台和架构重新编译它。

\n

请澄清事实真相:在这里,我想知道独立于机器的语言是什么样的。“x86-64 Windows”和“Arm Windows”是两个不同的平台,由于 CPU 架构不同,针对 x86-64 Windows 平台编译生成的可执行文件将无法在“ARM Windows”上执行。这表明C++是平台相关的;那么,我们如何在这里定义机器依赖或机器独立呢?如果一个平台的可执行文件不能在其他平台上运行,我们怎么能说C++是一种机器相关语言呢?

\n

c++ visual-c++ c++14 c++17 c++20

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

C++20 标准 (N4860) 中哪里规定内联函数必须在翻译单元中使用之前定义?

[dcl.constexpr]/1 :

说明constexpr符仅应用于变量或变量模板的定义或者函数或函数模板的声明。说明consteval符仅适用于函数或函数模板的声明。constexpr使用or说明符声明的函数或静态数据成员consteval隐式是内联函数或变量 ([dcl.inline])。如果函数或函数模板的任何声明具有constexprconsteval说明符,则其所有声明都应包含相同的说明符。

实施例1

constexpr void square(int &x);  // OK, declaration
constexpr int bufsz = 1024;     // OK, definition
constexpr struct pixel {        // error: pixel is a type
  int x;
  int y;
  constexpr pixel(int);         // OK, declaration
};
constexpr pixel::pixel(int a)
  : x(a), y(x)                  // OK, definition
  { square(x); }
constexpr pixel small(2);       // error: square not defined, so small(2) <<<<<<<<<<<<<<<<<<<<
                                // not constant ([expr.const]) so …
Run Code Online (Sandbox Code Playgroud)

c++ inline c++20 constexpr-function

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

我可以使用新的放置作为 bit_cast 吗?

我对绕过二进制类型转换限制的方法感兴趣,因为 bit_cast 使用复制到堆栈上的变量,这不是很快。但据我所知,普通类型不会在默认构造函数中初始化内存。这是否意味着,对于将 bit_casting 转换为普通类型,我们可以使用放置 new 和指向我们感兴趣的内存的指针,从而保持内存中的字节不变并避免不必要的复制?在这个问题上是否有我找不到的标准立场,并且禁止我将新的位置与一些“非主题”指针一起使用?

例如,第一个选项是其他人如何使用此功能。第二个选项是我想如何使用它。

#include <iostream>
using namespace std;
class Foo 
{ 
    private: int __unused0 : 31; //A little bit of binary magic
    private: int __unused1 :  1; 
    public: Foo() : __unused0(1), __unused1(1) {} //We're still saving trivially_copyable, so we're good
};

int main()
{
    //char bytes[1024];
    //auto* foo = new(bytes) Foo;
    
    Foo bytes{};
    auto* foo = new(&bytes) int;
    
    cout << *foo;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

UPD:这一切的目的是在不更改容器的情况下处理内存中的原始字节。在最简单的情况下,我需要像“检查寄存器中的高位”这样的小型优化,这是通过单个汇编命令来实现的,例如[x < 0]在处理结构中的位字段时创建一系列命令,例如[x & 0x80][x >> 7][x == …

c++ placement-new c++20 bit-cast

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

std::format 精度必须是 constexpr?

我有一个函数,用于获取输入双精度数的固定数字字符串。

函数是:

std::string to_fixed_string(double s, size_t n) {
  char buff[64];
  snprintf(buff, sizeof(buff), ("%." + std::to_string(n) + "f").c_str(), s); 
  return buff;
}
Run Code Online (Sandbox Code Playgroud)

最近我正在使用std::format,最重要的原因是std::format比snprintf更快。

但我发现 constexpr 限制使得这个函数不起作用。

有没有更有效的方法来实现这个功能?

例子是:

func(1.123123131, 3) -> "1.123"
func(1.123123131, 5) -> "1.12312"
Run Code Online (Sandbox Code Playgroud)

c++ c++20

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