Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否基于范围';对于';循环反对许多简单的算法?_C++_Algorithm_Stl_C++11_Foreach - Fatal编程技术网

C++ 是否基于范围';对于';循环反对许多简单的算法?

C++ 是否基于范围';对于';循环反对许多简单的算法?,c++,algorithm,stl,c++11,foreach,C++,Algorithm,Stl,C++11,Foreach,算法解决方案: std::generate(numbers.begin(), numbers.end(), rand); for (int& x : numbers) x = rand(); 基于范围的for循环解决方案: std::generate(numbers.begin(), numbers.end(), rand); for (int& x : numbers) x = rand(); 为什么我要在C++11中使用更详细的基于范围的for循环std::gener

算法解决方案:

std::generate(numbers.begin(), numbers.end(), rand);
for (int& x : numbers) x = rand();
基于范围的for循环解决方案:

std::generate(numbers.begin(), numbers.end(), rand);
for (int& x : numbers) x = rand();

为什么我要在C++11中使用更详细的基于范围的for循环
std::generate

for循环是否基于范围没有任何区别,它只简化了括号内的代码。算法更清晰,因为它们显示了意图。

在我看来,手动循环虽然可以减少冗长,但缺乏易懂的:

for (int& x : numbers) x = rand();
我不会使用这个循环来初始化由数字定义的范围,因为在我看来,它似乎是在一个数字范围内迭代,但实际上它不是(本质上),也就是说,它不是从范围中读取,而是向范围中写入

当您使用
std::generate
时,其意图更为明确

一,。在此上下文中初始化意味着为容器的元素赋予有意义的值。

第一个版本

std::generate(numbers.begin(), numbers.end(), rand);
告诉我们您想要生成一系列值

在第二个版本中,读者必须自己弄清楚这一点


节省打字时间通常是次优的,因为它通常会浪费在阅读时间上。大多数代码被读取的次数比输入的次数多得多

在我看来,有效的STL第43项:“优先选择手写循环的算法调用。”仍然是一个很好的建议。

我通常编写包装函数来摆脱
begin()
/
end()
地狱。如果您这样做,您的示例将如下所示:

my_util::generate(numbers, rand);
我相信它在传达意图和可读性方面都优于基于范围的for循环


话虽如此,我必须承认,在C++98中,一些STL算法调用产生了无法表达的代码,下面的“与手写循环相比,更喜欢算法调用”似乎不是一个好主意。幸运的是,兰博达斯已经改变了这一点

考虑下面的例子

任务:查找v中的第一个元素,即
>x

没有lambdas:

auto i = find_if( v.begin(), v.end(),
bind( logical_and<bool>(),
bind(greater<int>(), _1, x),
bind(less<int>(), _1, y) ) );
auto i=find_if(v.begin(),v.end(),
绑定(逻辑_和(),
绑定(更大的(),_1,x),
绑定(less(),_1,y));
和lambda

auto i=find_if( v.begin(), v.end(), [=](int i) { return i > x && i < y; } );
auto i=find_if(v.begin(),v.end(),[=](int i){return i>x&&i
我的答案是可能和否。如果我们谈论的是C++11,那么可能(更像是否)。例如,
std::For_each
即使与lambda一起使用,也非常烦人:

std::for_each(c.begin(), c.end(), [&](ExactTypeOfContainedValue& x)
{
    // do stuff with x
});
但使用基于范围的for要好得多:

for (auto& x : c)
{
    // do stuff with x
}
另一方面,如果我们谈论的是C++1y,那么我会说,不,这些算法不会被基于范围的for淘汰。在C++标准委员会中有一个研究小组正在研究C++中添加范围的建议,并且在多态LAMBDAS上也有工作。范围将不再需要使用一对迭代器,多态lambda将允许您不指定lambda的确切参数类型。这意味着
std::for_每个
都可以这样使用(不要把这当作硬事实,这就是今天的梦想):


就我个人而言,我最初读到:

std::generate(numbers.begin(), numbers.end(), rand);
for (int& x : numbers) x = rand();
是“我们分配给某个范围内的所有对象。该范围是
数字
。分配的值是随机的”

我对以下内容的初步解读:

std::generate(numbers.begin(), numbers.end(), rand);
for (int& x : numbers) x = rand();
是“我们正在对某个范围内的所有事物进行处理。该范围是
数字
。我们所做的是分配一个随机值。”

这些非常相似,但不完全相同。我想引起第一次阅读的一个可能的原因是,我认为关于这段代码最重要的事实是它分配给了范围。这就是你的“我为什么要……”。我使用<代码>生成< /C> >因为在C++ <代码> STD::生成< /COD>意味着“范围分配”。顺便说一句,正如std::copy所做的那样,两者之间的区别在于您从中分配的内容

不过,也有一些令人困惑的因素。与基于迭代器的算法相比,基于范围的for循环有一种更直接的方式来表示范围是
数字。这就是人们研究基于范围的算法库的原因:
boost::range::generate(number,rand)
看起来比std::generate版本更好

与此相反,基于for循环的范围中的
int&
是一个折痕。如果范围的值类型不是
int
,那么我们在这里做一些非常微妙的事情,这取决于它是否可以转换为
int&
,而
生成的
代码只取决于
rand
返回的值是否可以分配给元素。即使值类型是
int
,我仍然可能会停下来考虑它是否是。因此,
auto
,它推迟了对类型的思考,直到我看到分配了什么——使用
auto&x
我说“引用范围元素,不管它可能有什么类型”。回到C++03,算法(因为它们是函数模板)是隐藏精确类型的方法,现在它们是一种方法


我认为,最简单的算法与等效循环相比,只能获得边际收益,这种情况一直存在。基于范围的for循环改进了循环(主要是通过删除大部分样板文件,尽管其中还有一些内容)。因此,利润率越来越高,在某些特定情况下,你可能会改变主意。但是仍然有一个风格上的差异。

对于以迭代器为输入的算法来说,使用基于范围的循环,有些事情是无法(简单地)完成的。 例如,使用
std::generate

使用一个分布中的变量将容器填充到
limit
(排除在外,
limit
numbers
上的有效迭代器),其余容器填充另一个分布中的变量

std::generate(numbers.begin(), limit, rand1);
std::generate(limit, numbers.end(), rand2);

基于迭代器的算法可以更好地控制操作范围。

对于
std::generate
的特殊情况,我同意