标签: stl-algorithm

为什么std :: max_element需要ForwardIterator?

C++标准库的max_element算法需要将迭代器作为模型的输入传递ForwardIterator.

我的理解是通过指定您可以使用a 多次迭代相同的范围来ForwardIterator提炼.因此,多遍算法需要s.InputIteratorForwardIteratorForwardIterator

但是,max_element不是多遍算法 - 只需迭代一次范围就可以确定其最大元素.那么为什么max_element需要额外的功能ForwardIterator呢?

c++ iterator stl max stl-algorithm

12
推荐指数
1
解决办法
453
查看次数

使用copy和back_inserter将向量附加到自身时出现错误的结果

这个问题的启发,询问如何将一个向量附加到自身,我的第一个想法是以下(是的,我意识到insert现在是一个更好的选择):

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

int main() {
    std::vector<int> vec {1, 2, 3};
    std::copy (std::begin (vec), std::end (vec), std::back_inserter (vec));

    for (const auto &v : vec)
        std::cout << v << ' ';
}
Run Code Online (Sandbox Code Playgroud)

但是,这打印:

1 2 3 1 * 3
Run Code Online (Sandbox Code Playgroud)

每次运行程序时*都是不同的数字.只有2被替换的事实是特殊的,如果真的有解释,我会有兴趣听到它.继续,如果我附加到不同的向量(原始副本),它会正确输出.如果我在前一行之前添加以下行,它也会正确输出copy:

vec.reserve (2 * vec.size());
Run Code Online (Sandbox Code Playgroud)

std::back_inserter尽管事先没有预留内存,但我认为这是一种将元素添加到容器末端的安全方法.如果我的理解是正确的,复制线有什么问题?

我假设它与编译器无关,但我使用的是GCC 4.7.1.

c++ iterator stl undefined-behavior stl-algorithm

11
推荐指数
1
解决办法
1347
查看次数

使用带有std :: fill等算法的emplace

我使用的vector::emplace_back是为了避免在填充矢量时构造时间对象.这里有一个简化版本:

class Foo {
public:
    Foo(int i, double d) : i_(i), d_(d) {}
    /* ... */
};

std::vector<Foo> v;
v.reserve(10);
for (int i = 0; i < 10; i++)
    v.emplace_back(1, 1.0);
Run Code Online (Sandbox Code Playgroud)

但我想std::fill_n改用:

v.reserve(10);
std::fill_n(std::back_inserter(v), 10, Foo(1, 1.0));
Run Code Online (Sandbox Code Playgroud)

通过这种方式,将创建临时副本.我不知道emplace在这种情况下如何使用.我想我需要类似的东西std::back_emplacer,但我找不到这样的东西.这是C++ 11的一部分,但还没有在GCC中实现?如果它不是C++ 11的一部分,还有其他方法吗?

c++ stl stl-algorithm c++11

11
推荐指数
3
解决办法
4063
查看次数

std :: is_sorted和严格的比较少?

我不太了解std::is_sorted算法及其默认行为.如果我们查看cppreference,它会说默认情况下std::is_sorted使用<运算符.而不是那样,我发现使用<=是自然的.但我的问题是,对于以下数字列表:

1 2 3 3 4 5
Run Code Online (Sandbox Code Playgroud)

它会回来true,即使3 < 3应该false.怎么可能?

编辑:它似乎比我想象的更糟糕,因为std::less_equal<int>在这种情况下传递将返回false ...当我传递比较器函数时应用的条件是什么?

c++ sorting comparator stl-algorithm c++11

11
推荐指数
1
解决办法
1289
查看次数

为什么std :: copy_if签名不限制谓词类型

想象一下,我们有以下情况:

struct A
{
    int i;
};

struct B
{
    A a;
    int other_things;
};

bool predicate( const A& a)
{
    return a.i > 123;
}

bool predicate( const B& b)
{
    return predicate(b.a);
}

int main()
{
    std::vector< A > a_source;
    std::vector< B > b_source;

    std::vector< A > a_target;
    std::vector< B > b_target;

    std::copy_if(a_source.begin(), a_source.end(), std::back_inserter( a_target ), predicate);
    std::copy_if(b_source.begin(), b_source.end(), std::back_inserter( b_target ), predicate);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这两个调用都会std::copy_if产生编译错误,因为predicate()编译器不能接受函数的正确重载,因为std::copy_if模板签名接受任何类型的谓词:

template<typename _IIter, 
         typename _OIter, …
Run Code Online (Sandbox Code Playgroud)

c++ stl stl-algorithm c++11

11
推荐指数
2
解决办法
769
查看次数

在二维std :: array上使用std :: accumulate

给定二维数组

std::array<std::array<int, 2>, 3> m = {{ {1, 2}, {3, 4}, {5, 6} }};
Run Code Online (Sandbox Code Playgroud)

我正在寻找所有元素的总和 - 在这种情况下,21.如果数组是一维的,我可以写

auto sum = std::accumulate(m.begin(), m.end(), 0);
Run Code Online (Sandbox Code Playgroud)

但对于我的二维数组,这失败了,这是一个可以理解的错误

no match for 'operator+' (operand types are 'int' and 'std::array<int, 2ul>')
Run Code Online (Sandbox Code Playgroud)

我怎样才能优雅地为我的2D数组计算这个总和(避免for循环,更喜欢STL算法)?

是否可以像一维情况一样使用单线,或者它变得更复杂?

c++ multidimensional-array stl-algorithm c++11 c++14

11
推荐指数
2
解决办法
1320
查看次数

了解std :: transform以及如何击败它

我试图在一个简单的特定问题上理解面向数据的设计.如果我正在做一些非常愚蠢的事情,请提前向面向数据的设计人员道歉,但我很难理解为什么以及我的推理失败的原因.

假设我有一个简单的操作,,float_t result = int_t(lhs) / int_t(rhs).如果我将所有变量保存在相应的容器中,例如,std::vector<float_t>std::vector<int_t>,并且我使用std::transform,我得到正确的结果.然后,对于一个具体的例子,其中using float_t = floatusing int_t = int16_t我假定包装内的这些变量struct,在一个64位架构,并加以收集在容器内应该产生更好的性能.

我认为struct组成一个64位对象,并且单个内存访问struct将给我所需的所有变量.另一方面,当所有这些变量都收集在不同的容器中时,我将需要三种不同的内存访问来获取所需的信息.以下是我设置环境的方法:

#include <algorithm>
#include <chrono>
#include <cstdint>
#include <iostream>
#include <vector>

using namespace std::chrono;

template <class float_t, class int_t> struct Packed {
  float_t sinvl;
  int_t s, l;
  Packed() = default;
  Packed(float_t sinvl, int_t s, int_t l) : sinvl{sinvl}, s{s}, l{l} {}
  void comp() …
Run Code Online (Sandbox Code Playgroud)

c++ data-oriented-design stl-algorithm

11
推荐指数
1
解决办法
1121
查看次数

使用for_each的向量中每个元素的平方和

由于for_each接受的函数只接受一个参数(向量的元素),我必须定义一个static int sum = 0 某处,以便在调用for_each后可以访问它.我觉得这很尴尬.有没有更好的方法(仍然使用for_each)?

#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

static int sum = 0;
void add_f(int i )
{
    sum += i * i;

}
void test_using_for_each()
{
    int arr[] = {1,2,3,4};
    vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));

    for_each( a.begin(),a.end(), add_f);
    cout << "sum of the square of the element is  " << sum << endl;
}
Run Code Online (Sandbox Code Playgroud)

在Ruby中,我们可以这样做:

sum = 0
[1,2,3,4].each { |i| sum += i*i}   #local variable can be …
Run Code Online (Sandbox Code Playgroud)

c++ vector stl-algorithm

10
推荐指数
3
解决办法
8166
查看次数

std :: ostream_iterator阻止最后一项使用分隔符

有没有办法使用std :: ostream_iterator(或类似的),以便不为最后一个元素放置分隔符?

#include <iterator>
#include <vector>
#include <algorithm>
#include <string>


using namespace std;
int main(int argc, char *argv[]) {
    std::vector<int> ints = {10,20,30,40,50,60,70,80,90};
    std::copy(ints.begin(),ints.end(),std::ostream_iterator<int>(std::cout, ","));
}
Run Code Online (Sandbox Code Playgroud)

会打印

10,20,30,40,50,60,70,80,90,

我试图避免落后的分隔符.我想要打印

10,20,30,40,50,60,70,80,90

当然,你可以使用一个循环:

for(auto it = ints.begin(); it != ints.end(); it++){
  std::cout << *it;
  if((it + 1) != ints.end()){           
    std::cout << ",";
  }
}
Run Code Online (Sandbox Code Playgroud)

但是考虑到基于C++ 11范围的循环,跟踪位置是很麻烦的.

int count = ints.size();
for(const auto& i : ints){
  std::cout << i;
  if(--count != 0){
    std::cout << ",";
  }     
}
Run Code Online (Sandbox Code Playgroud)

我愿意使用Boost.我查看了boost :: algorithm :: …

c++ iostream stl-algorithm

10
推荐指数
1
解决办法
6620
查看次数

为什么std :: find_if(first,last,p)不能通过引用获取谓词?

我正在查看std::find_ifcppreference.com上的各种签名,我注意到采用谓词函数的风格似乎是按值接受它:

template< class InputIt, class UnaryPredicate >
InputIt find_if( InputIt first, InputIt last,
             UnaryPredicate p );
Run Code Online (Sandbox Code Playgroud)

如果我正确理解它们,带有捕获变量的lambdas会为其数据的引用或副本分配存储空间,因此可能会出现"按值传递"意味着会为调用复制捕获数据的副本.

另一方面,对于函数指针和其他直接可寻址的东西,如果直接传递函数指针,而不是通过引用指针(指向指针),性能应该更好.

首先,这是正确的吗?UnaryPredicate以上是否是一个按值参数?

第二,我对传递lambdas的理解是否正确?

第三,在这种情况下,是否有理由通过价值而非参照?更重要的是,是不是有一些足够模糊的语法(hello,通用引用)可以让编译器做任何想要获得最大性能的东西?

c++ pass-by-value stl-algorithm c++17

10
推荐指数
2
解决办法
765
查看次数