标签: c++14

如何在现代C++中实现经典排序算法?

std::sort算法(及其同类std::partial_sortstd::nth_element从C++标准库)是在大多数实现的更基本的排序算法复杂和混合合并,如选择排序,插入排序,快速排序,归并排序,或堆排序.

这里和姐妹网站上有很多问题,例如https://codereview.stackexchange.com/,与错误,复杂性以及这些经典排序算法的实现的其他方面有关.大多数提供的实现包括原始循环,使用索引操作和具体类型,并且在正确性和效率方面分析通常是非常重要的.

:如何使用现代C++实现上述经典排序算法?

  • 没有原始循环,但结合了标准库的算法构建块<algorithm>
  • 迭代器接口模板的使用,而不是索引操作和具体类型
  • C++ 14风格,包括完整的标准库,以及语法降噪器,如auto模板别名,透明比较器和多态lambda.

备注:

  • 有关排序算法实现的进一步参考,请参阅Wikipedia,Rosetta Codehttp://www.sorting-algorithms.com/
  • 根据Sean Parent的惯例(幻灯片39),原始循环for比使用运算符的两个函数的组合更长.所以f(g(x));f(x); g(x);f(x) + g(x);不生循环,也不是在环路selection_sortinsertion_sort下方.
  • 我遵循Scott Meyers的术语来表示当前的C++ 1y已经作为C++ 14,并且将C++ 98和C++ 03都表示为C++ 98,所以不要因此而激怒我.
  • 正如@Mehrdad的评论中所建议的那样,我在答案的最后提供了四个实现作为实例:C++ 14,C++ 11,C++ 98和Boost and C++ 98.
  • 答案本身仅以C++ 14的形式呈现.在相关的地方,我表示各种语言版本不同的语法和库差异.

c++ sorting algorithm c++-faq c++14

322
推荐指数
2
解决办法
3万
查看次数

现代C++可以免费获得性能吗?

有时声称即使仅编译C++ 98代码,C++ 11/14也可以提高性能.理由通常是移动语义,因为在某些情况下,rvalue构造函数是自动生成的,或者现在是STL的一部分.现在我想知道这些案例以前是否已经由RVO或类似的编译器优化处理过了.

那么我的问题是,如果你能给我一个C++ 98代码的实际例子,使用支持新语言特性的编译器,无需修改就可以更快地运行.我确实理解标准符合编译器不需要执行复制省略,因此移动语义可能会带来速度,但我希望看到一个较少病态的案例,如果你愿意的话.

编辑:为了清楚,我不是在问新的编译器是否比旧的编译器更快,而是如果有代码将-std = c ++ 14添加到我的编译器标志它会运行得更快(避免副本,但如果你除了移动语义之外还能提出其他任何东西,我也会感兴趣)

c++ performance move-semantics c++11 c++14

205
推荐指数
2
解决办法
1万
查看次数

C++ 11,14,17或20是否为pi引入了标准常量?

C和C++中的数字pi存在一个相当愚蠢的问题.据我知道M_PI的定义math.h是没有任何标准要求.

新的C++标准在标准库中引入了许多复杂的数学 - 双曲函数,std::hermite以及std::cyl_bessel_i不同的随机数生成器等等.

是否有任何"新"标准为pi带来了一个常数?如果没有 - 为什么?没有它,所有这些复杂的数学如何运作?

我知道关于C++中pi的类似问题(它们已经有几年了,而且标准已经很久了); 我想知道问题的当前状态.

我也非常感兴趣为什么 C++仍然没有pi常量,但有很多更复杂的数学.

UPD:我知道我可以将自己定义为4*atan(1)或acos(1)或double pi = 3.14.当然.但为什么在2018年我仍然必须这样做?没有pi,标准数学函数如何工作?

c++ language-lawyer c++11 c++14 c++17

161
推荐指数
5
解决办法
2万
查看次数

Lambda捕获为const引用?

是否可以通过lambda表达式中的const引用进行捕获?

我希望下面标记的作业失败,例如:

#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";

    for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
      {
        best_string = s; // this should fail
      }
    );
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

更新:由于这是一个老问题,如果C++ 14中有设施来帮助解决这个问题,那么更新它可能会更好.C++ 14中的扩展是否允许我们通过const引用捕获非const对象?(2015年8月)

c++ lambda c++11 c++14

151
推荐指数
6
解决办法
5万
查看次数

`void_t`是如何工作的?

我观看了Walter Brown在Cppcon14上关于现代模板编程(第一部分,第二部分)的演讲,他在演讲中展示了他的void_tSFINAE技术.

示例:
给定一个简单的变量模板,该模板计算void所有模板参数是否格式正确:

template< class ... > using void_t = void;
Run Code Online (Sandbox Code Playgroud)

以及检查是否存在名为member的成员变量的以下特征:

template< class , class = void >
struct has_member : std::false_type
{ };

// specialized as has_member< T , void > or discarded (sfinae)
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : std::true_type
{ };
Run Code Online (Sandbox Code Playgroud)

我试图理解为什么以及如何运作.因此一个小例子:

class A {
public:
    int member;
};

class B {
};

static_assert( has_member< A …
Run Code Online (Sandbox Code Playgroud)

c++ templates sfinae c++14

140
推荐指数
2
解决办法
1万
查看次数

我什么时候应该使用C++ 14自动返回类型扣除?

随着GCC 4.8.0的发布,我们有一个支持自动返回类型推导的编译器,这是C++ 14的一部分.有了-std=c++1y,我可以这样做:

auto foo() { //deduced to be int
    return 5;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:我应该何时使用此功能?什么时候需要,何时使代码更清洁?

场景1

我能想到的第一个场景是可能的.每个可以用这种方式编写的函数都应该是.这个问题是它可能并不总是使代码更具可读性.

情景2

下一个场景是避免更复杂的返回类型.作为一个很轻的例子:

template<typename T, typename U>
auto add(T t, U u) { //almost deduced as decltype(t + u): decltype(auto) would
    return t + u;
}
Run Code Online (Sandbox Code Playgroud)

我不相信这确实会成为一个问题,虽然我认为在某些情况下明确依赖于参数的返回类型可能更清楚.

场景3

接下来,为了防止冗余:

auto foo() {
    std::vector<std::map<std::pair<int, double>, int>> ret;
    //fill ret in with stuff
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,我们有时可以return {5, 6, 7};代替向量,但这并不总是有效,我们需要在函数头和函数体中指定类型.这纯粹是多余的,自动返回类型扣除使我们免于冗余.

场景4

最后,它可以用来代替非常简单的功能:

auto position() {
    return pos_;
}

auto area() {
    return …
Run Code Online (Sandbox Code Playgroud)

c++ return-type-deduction c++14

137
推荐指数
5
解决办法
4万
查看次数

#pragma曾经是C++ 11标准的一部分吗?

传统上,避免C++中多个头部包含的标准和可移植方法是使用#ifndef - #define - #endif预编译器指令方案,也称为宏保护方案(参见下面的代码片段).

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif
Run Code Online (Sandbox Code Playgroud)

然而,在大多数实现/编译器中(见下图),有一个更"优雅"的替代方案,其功能与调用的宏保护方案相同#pragma once.#pragma once与宏保护方案相比具有几个优点,包括更少的代码,避免名称冲突,有时提高编译速度.

在此输入图像描述

做了一些研究,我意识到尽管#pragma once几乎所有已知的编译器都支持指令,但是指令是否#pragma once是C++ 11标准的一部分还是存在紊乱.

问题:

  • 有人可以澄清#pragma once指令是否属于C++ 11标准的一部分吗?
  • 如果它不是C++ 11标准的一部分,是否有计划将其包含在以后的版本中(例如,C++ 14或更高版本)?
  • 如果有人可以进一步详细说明使用这些技术中的任何一种(即,宏观防护对比#pragma once)的优点/缺点,那也是很好的.

c++ macros header-files c++11 c++14

137
推荐指数
2
解决办法
4万
查看次数

在std :: vector :: erase()和std :: deque :: erase()中复制/移动赋值

在回答的过程中的另一个问题,我偶然发现稍有不同的措辞为std::vector::erase()std::deque::erase().

这就是C++ 14所说的std::deque::erase([deque.modifiers]/4-6强调我的):

效果: ......

复杂性:对析构函数的调用次数与擦除的元素数相同,但对赋值运算符的调用次数不超过删除元素之前的元素数量和次要元素数量之后的次数.擦除元素.

抛出:除非复制构造函数,移动构造函数,赋值运算符或移动赋值运算符抛出异常,否则无效T.

以下是关于std::vector::erase([vector.modifiers]/3-5)的内容:

效果: ......

复杂性:的析构函数T被调用的次数等于擦除的元件的数量的数量,但该移动赋值运算符T被称为的次数等于在向量元素的擦除元件后的数目的数目.

抛出:除非复制构造函数,移动构造函数,赋值运算符或移动赋值运算符抛出异常,否则无效T.

正如您所看到的,两者的异常规范是相同的,但是为了std::vector明确提到它,调用了移动赋值运算符.

还有的要求TMoveAssignableerase()两者的工作std::vectorstd::deque(表100),但这并不意味着移动赋值运算符的存在:一个可以定义一个拷贝赋值运算符,而不是定义移动赋值操作符,而这个班会是MoveAssignable.

为了以防万一,我检查了GCC和Clang,std::vector::erase()如果没有移动赋值运算符,确实调用了复制赋值运算符,并且std::deque::erase()执行相同的操作(DEMO).

所以问题是:我错过了什么,或者这是标准中的(编辑)问题?

更新: 我已经提交了LWG问题#2477.

c++ language-lawyer c++14

135
推荐指数
1
解决办法
4084
查看次数

decltype(auto)有哪些用途?

在c ++ 14 decltype(auto)中引入了成语.

通常,它的用途是允许auto声明使用decltype给定表达式的规则.

搜索成语的"好"用法示例我只能想到以下内容(由Scott Meyers提供),即函数的返回类型推导:

template<typename ContainerType, typename IndexType>                // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
  authenticateUser();
  return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}
Run Code Online (Sandbox Code Playgroud)

这个新语言功能有用吗?

c++ decltype auto return-type-deduction c++14

133
推荐指数
2
解决办法
5万
查看次数

std :: make_unique和std :: unique_ptr之间的差异与new

是否std::make_unique有像任何效率优势std::make_shared

与手动构建相比std::unique_ptr:

std::make_unique<int>(1);         // vs
std::unique_ptr<int>(new int(1));
Run Code Online (Sandbox Code Playgroud)

c++ smart-pointers unique-ptr c++11 c++14

118
推荐指数
4
解决办法
5万
查看次数