我写了一个我想声明为 const 的方法,但编译器抱怨。我追查了一下,发现是方法的这部分造成了困难:
bool ClassA::MethodA(int x)
{
bool y = false;
if(find(myList.begin(), myList.end(), x) != myList.end())
{
y = true;
}
return y;
}
Run Code Online (Sandbox Code Playgroud)
方法中发生的事情比这更多,但是在剥离所有其他内容后,这部分不允许该方法为 const。为什么stl find算法会阻止方法成为const?它是否以任何方式更改列表?
我有一个类,有一个返回计数的函数,如下所示:
class CTestClass
{
public:
// ...
size_t GetCount()const;
// ...
};
Run Code Online (Sandbox Code Playgroud)
在我的程序中的某个地方,我有一个该类对象的向量.我有一个函数来获取总计数(CTestClass :: GetCount()的结果总和),像普通循环一样实现:
size_t sum = 0;
for(vector<CTestClass>::const_iterator it = v.begin(); it != v.end(); ++it)
{
sum += it->GetCount();
}
Run Code Online (Sandbox Code Playgroud)
我想重构它以使用标准库中的可用设施,我想到了accumulate.我已经能够通过使用一个函数对象(简单)来做到这一点,但我几乎可以肯定它可以在不声明另一个对象的情况下完成(我没有C++ 11或者提升,所以没有lambda,但是我有TR1).
在寻找答案时,我发现了这些资源,但他们没有解决问题:
accumulate,plus和
bind,但使用的是数据成员,而不是成员函数. 那么,有没有办法使用bind或类似的东西来做到这一点?
在GCC 5.4.0中stl_algobase.h我们有:
template<typename _ForwardIterator, typename _Tp>
inline typename
__gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, void>::__type
__fill_a(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __value)
{
for (; __first != __last; ++__first)
*__first = __value;
}
template<typename _ForwardIterator, typename _Tp>
inline typename
__gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, void>::__type
__fill_a(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __value)
{
const _Tp __tmp = __value;
for (; __first != __last; ++__first)
*__first = __tmp;
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么标量的变体比一般变体有任何优势.我的意思是,它们不会被编译成完全相同的东西吗?__value从堆栈加载到寄存器中并在整个循环中使用该寄存器?
并行 STL 算法是否符合std::back_insert_iterator??
我可能误解了std::par和之间的区别std::par_vec,是否std::par_vec意味着需要预先分配输出范围?
代码示例:
auto numbers = {1,2,3,4,5,6};
auto squared = std::vector<int>{};
std::transform(
**std::par/std::par_vec,**
numbers.begin(),
numbers.end(),
std::back_inserter(squared),
[](auto val) {
return val*val;
}
);
Run Code Online (Sandbox Code Playgroud)
更新
简化问题作为我的第一个问题是误读文章的结果。
我的目标是尝试解决这个问题:从 end 中删除向量中的所有空元素。使用擦除删除成语。
这个想法是在给定std::vector<std::string>的字符串a中删除从末尾开始的所有元素,这些元素是空的(等于空白)。当发现非空元素时,应停止删除元素。
例子:
vec = { " ", "B", " ", "D", "E", " ", " ", " " };
Run Code Online (Sandbox Code Playgroud)
移除后:
vec = { " ", "B", " ", "D", "E"};
Run Code Online (Sandbox Code Playgroud)
这是我尝试的解决方案:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <iterator>
int main()
{
std::vector<std::string> vec = { " ", "B", " ", "D", "E", " ", " ", " " };
bool notStop = true;
auto removeSpaceFromLast = [&](const std::string& …Run Code Online (Sandbox Code Playgroud) 根据这篇文章,一种可能的实现std::unique是
template<class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last)
{
if (first == last)
return last;
ForwardIt result = first;
while (++first != last) {
if (!(*result == *first) && ++result != first) {
*result = std::move(*first);
}
}
return ++result;
}
Run Code Online (Sandbox Code Playgroud)
但是,我不明白迭代器比较的用途是什么?为什么if (!(*result == *first) && ++result != first)而不只是if (!(*result++ == *first))?比较两个迭代器的目的是什么?
在阅读了std::next_permutation Implementation Explanation的优秀答案后,我提出了这个问题。请参阅该帖子以了解 STL 使用的算法的说明,但我将在此处复制代码以供您参考
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
template<typename It>
bool next_permutation(It begin, It end)
{
if (begin == end)
return false;
It i = begin;
++i;
if (i == end)
return false;
i = end;
--i;
while (true)
{
It j = i;
--i;
if (*i < *j)
{
It k = end;
while (!(*i < *--k))
/* pass */;
iter_swap(i, k);
reverse(j, end);
return true;
}
if (i == begin) …Run Code Online (Sandbox Code Playgroud) 我经常发现自己想要根据向量的索引而不是值来过滤向量。
auto some_values = std::vector{1, 0, 4, 6, 2};
// Somewhere I figure out which items to remove.
// This may be from user interaction or something
// nothing to do with the original values:
const auto removing = std::vector<bool>{0, 0, 1, 0, 1};
Run Code Online (Sandbox Code Playgroud)
erase_if所以,我很想像这样使用:
std::erase_if(some_values, [it = removing.begin()](auto) mutable {return *it++;});
Run Code Online (Sandbox Code Playgroud)
它似乎适用于 gcc 和 clang。但是, std::erase cppref 页面上似乎没有任何关于谓词调用顺序的内容,所以我认为这是未定义的行为?
与 相同的问题std::remove_if。请注意,压缩范围不适用于大多数压缩选项,因为通常生成的范围无法调整基础数据的大小。
使用 for 循环并创建数组的副本并不是太多的样板文件,但我目前正在将过滤器应用于一些低级代码,在这些代码中我无法复制所有数据。有些数据会很大,需要在这些过滤操作期间做出响应。
最坏的情况我可以添加这样的函数来解决问题:
template <class T, auto N, class Pred>
size_t …Run Code Online (Sandbox Code Playgroud) 我有2个向量,包含,让我们说Person(姓名,姓氏等)对象.我想取一个向量(让它命名为"大")然后对于这个向量中的每个元素在第二个中找到对应的元素("小")并将一些数据从"小"向量元素合并到"大"向量元件.此操作与SQL术语中的左连接非常相似,但具有额外的数据合并.最简单的方法是进行2个循环,但这将导致O(n ^ 2)时间复杂度.我可以用STL算法做得更好吗?
我已经定义了自己的结构
struct element {
int id;
float value;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用它std::set.我想使用该set_difference算法(就像上一个问题中已经提到的那样,用于确定两个集合的区别.当我尝试调用代码时,编译会停止,并显示以下错误消息:
/usr/include/c++/4.2.1/bits/stl_algobase.h:268: error: passing
'const element' as 'this' argument of 'element& element::operator=(const element&)'
discards qualifiers
Run Code Online (Sandbox Code Playgroud)
一个最小的例子可能如下所示:
std::set<struct element> s1;
std::set<struct element> s2;
std::set<struct element> s3;
element e1 = { 1, 11.0 };
element e2 = { 2, 22.0 };
element e3 = { 3, 33.0 };
s1.insert(e1);
s1.insert(e2);
s2.insert(e2);
s2.insert(e3);
set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), s3.begin());
Run Code Online (Sandbox Code Playgroud)