我试图理解这段代码,但我不明白为什么这个版本
for (; first != last; ++first)
init = std::move(init) + *first;
比这快
for (; first != last; ++first)
init += *first;
template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = init + *first;
}
return init;
}
在C++20之后它变成了
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first; // std::move since C++20
}
return init;
}
我只是想知道,使用std::move是否有任何真正的改进。
编辑2
#include <utility>
#include <chrono>
#include <iostream>
using ck = std::chrono::high_resolution_clock;
std::string
test_no_move(std::string str) {
std::string b = "t";
int count = 0;
while (++count < 100000)
str = std::move(str) + b; // Without std::move
return str;
}
std::string
test_with_move(std::string str) {
std::string b = "t";
int count = 0;
while (++count < 100000) // With std::move
str = str + b;
return str;
}
int main()
{
std::string result;
auto start = ck::now();
result = test_no_move("test");
auto finish = ck::now();
std::cout << "Test without std::move " << std::chrono::duration_cast<std::chrono::microseconds>(finish - start).count() << std::endl;
start = ck::now();
result = test_with_move("test");
finish = ck::now();
std::cout << "Test with std::move " << std::chrono::duration_cast<std::chrono::microseconds>(finish - start).count() << std::endl;
return 0;
}
对于具有非平凡move语义的类型,它可能更快。考虑累积std::vector
足够长的字符串:
std::vector<std::string> strings(100, std::string(100, ' '));
std::string init;
init.reserve(10000);
auto r = accumulate(strings.begin(), strings.end(), std::move(init));
对于不带std::move
的累加
,
std::string operator+(const std::string&, const std::string&);
将被使用。在每次迭代中,它将为产生的字符串分配堆上的存储,以便在下一次迭代时丢弃它。
std::string operator+(std::string&&, const std::string&);
without std::move
n_allocs = 199
with std::move
n_allocs = 0
对于像int
这样的内置类型,move只是一个拷贝--没有什么可以移动的。对于优化的构建,很可能会得到完全相同的程序集代码。如果您的基准测试显示任何速度提高/下降,很可能您没有正确地进行(没有优化、噪声、代码优化掉了,等等)。
我想知道为什么需要(又名reduce)第3个参数。对于那些不知道是什么的人,它的用法如下: 调用等同于: 还有可选第4个参数,它允许用任何其他操作替换加法。 我听说的一个基本原理是,如果你不需要加起来,而是乘一个向量的元素,我们需要其他的(非零)初始值: 但是为什么不像Python那样-为设置初始值,并使用从开始的范围。类似这样的事情: 这对任何行动都管用。为什么需要第三个参数?
考虑以下示例代码,其中线程A在队列上推送函数,线程B在从队列中弹出时执行这些函数: 其中是一个并发队列,它有一个和一个函数,每个返回一个指示给定操作是否成功。因此,如果已满,则返回,如果为空,则返回。 现在我想知道代码是否在所有情况下都是线程安全的。让我们假设线程B的失败并即将调用
自相矛盾的是,如果有一个像std::shared_ptr的指针但是不参与资源所有权共享的指针是很方便的。换句话说,是一个类似std::shared_ptr但不影响对象引用计数的指针。这种类型的智能指针必须要解决一个std::shared_ptr不存在的问题:可能指向已经销毁的对象。一个真正的智能指针应该跟踪所值对象,在悬空时知晓,悬空(dangle)就是指针指向的对象不再存在。这就是对std::w
我正在尝试运行下面的C代码,我得到这个错误:任何人都可以帮我澄清为什么这是问题 输入:输入/text_4.txt 9 在抛出'std::bad_alloc'什么()的实例后终止调用:std::bad_alloc中止(核心转储)在读取了几个类似的线程后,解决方案是检查动态存储分配。但是,我的代码没有任何动态分配的内存 输入文件text_4.txt: 这是因为在波德莱尔三个年轻人的生活中,没有多少快乐
问题内容: 我已经实现了一定数量的所有素数的列表。我试图做的事情很难解释,所以我只用一些硬代码展示一下: 所以从本质上讲,我试图从上一个列表中按顺序取出一个元素,然后按指数倍增,然后将其追加到其他列表中。 我意识到我可以做到这一点,这可能会更容易: 我需要一些想法才能在某种程度上做到这一点。 问题答案: 您需要 累积产品 清单。这是一个简单的食谱: 另一种方法,使用itertools: 或者,也许
我想在Spark中做累积和。以下是注册表(输入): 配置单元查询: 输出: 使用火花逻辑,我得到相同的输出: 然而,当我在spark cluster上尝试这个逻辑时,的值将是累积和的一半,有时它是不同的。我不知道为什么它会发生在spark cluster上。是因为分区吗? 如何计算spark cluster上一列的累积和?