为什么 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++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++中什么效率更高?
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)
?
我需要计算D维函数的函数值和梯度并将这些值加在一起。D我认为简单地将梯度部分存储在第一个分量中并将函数值存储在D+1维向量的最后一个分量中将是有益于计算的。
但是,如何从该维向量中提取第一个D分量(即梯度部分) ?D+1我知道可以选择切片,但我不想在这里添加任何无意义的开销。所以,我尝试简单地reinterpret_cast<Eigen::Vector<T, D>&>在我的上做一个Eigen::Vector<T, D + 1>并且它起作用了;但这真的能保证有效(并且安全)吗?
我正在尝试 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) 我试图在全局级别定义两个无序映射,我用循环定义它们,并且我不想将循环放入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(),它应该可以工作。但我不想那样做。 …
https://www.geeksforgeeks.org/introduction-to-c-programming-language/ \n在一些按键和功能下
\n\n\n机器独立但平台相关:C++ 可执行文件不是平台无关的(Linux 上编译的程序无法在 Windows 上运行\xe2\x80\x99),但它们是机器无关的。
\n
平台无关:这部分语句正确指出 C++ 可执行文件不是平台无关的。由于系统库、系统调用和可执行文件格式的差异,在一种操作系统(例如 Linux)上编译的程序通常不会直接在另一种操作系统(例如 Windows)上运行。
\n机器独立:本文中的术语“机器独立”可能会产生误导或不精确。编译的 C++ 可执行文件也不是真正独立于机器的。它们是机器相关的,因为它们被编译为特定于目标 CPU 架构的机器代码。例如,为 x86 架构编译的代码将无法在基于 ARM 的计算机上运行。
\n那么为什么在每一篇文章中都写到 C++ 是机器独立的呢?
\nC++ 可执行文件既不独立于平台(它们依赖于操作系统),也不独立于机器(它们依赖于 CPU 架构)。它们特定于平台和机器。
\n在实践中,如果你想在不同的平台或机器上运行 C++ 程序,通常需要针对每个特定的平台和架构重新编译它。
\n请澄清事实真相:在这里,我想知道独立于机器的语言是什么样的。“x86-64 Windows”和“Arm Windows”是两个不同的平台,由于 CPU 架构不同,针对 x86-64 Windows 平台编译生成的可执行文件将无法在“ARM Windows”上执行。这表明C++是平台相关的;那么,我们如何在这里定义机器依赖或机器独立呢?如果一个平台的可执行文件不能在其他平台上运行,我们怎么能说C++是一种机器相关语言呢?
\n说明
constexpr符仅应用于变量或变量模板的定义或者函数或函数模板的声明。说明consteval符仅适用于函数或函数模板的声明。constexpr使用or说明符声明的函数或静态数据成员consteval隐式是内联函数或变量 ([dcl.inline])。如果函数或函数模板的任何声明具有constexpr或consteval说明符,则其所有声明都应包含相同的说明符。Run Code Online (Sandbox Code Playgroud)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 …
我对绕过二进制类型转换限制的方法感兴趣,因为 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 == …
我有一个函数,用于获取输入双精度数的固定数字字符串。
函数是:
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++ ×10
c++20 ×10
c++-concepts ×2
stl ×2
bit-cast ×1
c++14 ×1
c++17 ×1
eigen ×1
inline ×1
std-ranges ×1
stdmap ×1
visual-c++ ×1