是“使用std :: begin;”一个好习惯?

时间:2015-07-24 07:51:32

标签: c++ c++11 coding-style standards

正如我所读到的,由于数组支持,begin(some_vector)some_vector.begin()更标准......而且我也知道,使用using keyword并不是真正理想的行为。但是,我也看到很多代码只包含这两个usings

using std::begin;
using std::end;

这被认为是好的还是坏的做法?特别是当需要许多beginend时?

4 个答案:

答案 0 :(得分:7)

  

正如我所读到的,由于数组支持,begin(some_vector)some_vector.begin()更标准

它不是“更标准”,都是100%标准。它更通用,因为它适用于数组,但实际上并不常见的是拥有一个对象而不知道它是一个数组还是一个容器类型。如果您知道某个数组是数组,那么使用std::begin(a)但是如果您知道某些内容不是数组,则使用也适用于数组的表单没有任何优势。如果您处于一个通用的上下文中,那么std::begin适用于这两种情况。

  

using关键字的使用并不是真正理想的行为。

这是值得商榷的。有很好的理由避免在大多数情况下使用指令(即using namespace foo),但相同的参数不适用于引入单个名称的使用声明(即using foo::bar)。例如,使用std::swap的推荐方法是using std::swap,因此using关键字通常不合适。

  

这被认为是好的还是坏的做法?特别是当需要许多开始和结束时?

我会说,总的来说这是一个坏主意。正如其他答案所解释的那样,它允许ADL找到beginend,但这不一定是好事。为beginend启用ADL可能会导致问题,这就是为什么我们在最后一分钟将基于范围的for更改为而不是使用using std::begin; using std::end;来避免含糊不清,请参阅N3257了解详细信息。

答案 1 :(得分:6)

ADL帮助有帮助。类似的东西:

template<typename T, typename F>
void apply(T& v, const F& f)
{
   using std::begin;
   using std::end;
   std::for_each(begin(v), end(v), f);
}

因此,我们可以使用具有apply函数和经典C数组的类型调用begin/end

在其他情况下,它实际上可以在源文件中使用using指令,在很小的范围内等等,但在标题中使用它是不好的。

答案 2 :(得分:3)

  

这被认为是好的还是坏的做法?

这在很大程度上取决于背景;我认为答案同样适用于通过using引入名称的更一般性问题。限制using使用范围,以获得更易读的代码(例如函数级别范围);根据需要使用它,小心使用。

这里一个特别有趣的案例围绕着ADL。

template <class Container>
void func(Container& c)
{
  std::for_each(begin(c), end(c), /* some functor*/);
}

ADL已在使用中,因为如果容器来自std命名空间,则会找到std::beginstd::end。如果容器来自自定义命名空间,则可以在该命名空间中找到beginend函数(对于此讨论,我假设容器提供程序也提供了这些)。

如果容器是普通的C风格数组,则不会找到数组形式std::begin(T (&array)[N]),因为C风格的数组不是std命名空间。在此处引入using std::begin允许代码用于数组和容器。

template <class Container>
void func(Container& c)
{
  using std::begin; // if c is an array, the function will still compile
  using std::end;
  std::for_each(begin(c), end(c), /* some functor*/);
}
// ...
int a[100];
func(a); // works as expected

Demo

答案 3 :(得分:1)

这取决于。不鼓励在头文件中使用声明(以及更多,使用指令)。但是,如果在函数体内部使用了很多次来自另一个命名空间的一个或多个函数,则使用声明/指令(放在函数体内,因此仅限于其范围)可以使代码更具可读性。