赞
踩
如下,声明一个返回类型为auto的函数,让它依据函数调用时传入的参数进行推导,指定C++11标准进行编译,我用的是clang编译器,编译命令为:clang++ -std=c++11 1.1.cpp
,发现会有编译错误,并且报告说这是C++14的新特性,如下:
/**
* @file 1.1.cpp
* @brief
* @author YongDu
* @date 2021-07-18
*/
#include <iostream>
using namespace std;
auto func(int i) { return i; }
int main() {
cout << func(4) << endl;
return 0;
}
用C++14编译:clang++ -std=c++14 1.1.cpp
,发现没有问题,程序也正常执行。
同时,返回值类型也可以用在模板中,不像C++11需要使用尾置返回类型:
#include <iostream> using namespace std; template <typename T1, typename T2> auto Sum(T1 t1, T2 t2) { return t1 + t2; } int main() { cout << Sum(2, 3) << endl; cout << Sum(1.1, 2.2) << endl; return 0; } // 5 // 3.3
注意:
#include <iostream>
using namespace std;
auto func(bool flag) {
if (flag)
return 1;
else
return 2.2;
}
auto func() { return {1, 2, 3}; }
// error: cannot deduce return type from initializer list
struct A {
virtual auto func() {}
};
// error: function with deduced return type cannot be virtual
返回类型声明可以用在前向声明,但是在使用它们之前,翻译单元中必须能够得到函数定义
返回类型推导可以用在递归函数中,但是递归调用必须至少以一个返回语句作为先导,以便编译器推导出返回类型
auto fib(int n) {
if (0 == n || 1 == n) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
C++14支持变量模板,如下:
#include <iostream> using namespace std; template <class T> constexpr T pi = T(3.1415926535897932385L); // 变量模板 template <class T> T circular_area(T r) { // 函数模板 return pi<T> * r * r; // pi<T> 是变量模板实例化 } int main() { cout << circular_area(2) << endl; // 12 cout << circular_area(2.0) << endl; // 12.5664 return 0; }
template <typename T, typename U> struct A { T t; U u; }; template <typename T> using B = A<T, int>; int main() { B<double> b; b.t = 10; b.u = 20; cout << b.t << ", " << b.u << endl; return 0; }
在C++11中,lambda表达式参数需要使用具体的类型说明:
auto f = [] (int a) { return a; };
在C++14中,对此进行优化,lambda表达式参数可以为auto类型,类似于函数模板:
auto f = [](auto a) { return a; };
cout << f(1) << endl;
cout << f(1.1) << endl;
在C++14中,我们可以对捕获列表的捕获变量“赋值”。如下代码:
#include <cmath>
#include <iostream>
using namespace std;
int main() {
int a = 2;
[a = sin(a)]() {
cout << a << endl; // 0.909297
cout << cos(a) << endl; // 0.6143
}();
cout << a << endl; // 2
cout << cos(a) << endl; // -0.416147
return 0;
}
C++14中的这个新特性允许了在捕获列表中定义前面没有出现过的变量,但必须赋予一个值,并且不使用类型说明符和auto,类型由编译器自动推断。
C++11中的常量表达式函数:
如下代码:
constexpr int factorial(int n) { // 在C++11或者C++14中均可以编译通过
return n <= 1 ? 1 : (n * factorial(n - 1));
}
constexpr int factorial(int n) { // 只有在C++14中可以编译通过
int ret = 1;
for (int i = 1; i <= n; ++i) {
ret *= i;
}
return ret;
}
C++14中增加了[[deprecated]]标记,可以修饰类、函数、变量等,当程序中使用了被其修饰的模块时,编译器会产生告警,提示用户该标记标记的内容将来可能会被废弃,尽量不要使用。
struct [[deprecated]] Tmp {};
int a = 0b0001'0011'1010;
double b = 3.14'1234'1234'1234;
C++11中没有std::make_unique
,在C++14中实现了这个方法。
struct A {};
std::unique_ptr<A> ptr = std::make_unique<A>();
C++14中通过std::shared_timed_mutex
和std::shared_lock
实现读写锁,保证多个线程可以同时读,但是写线程必须独立运行,写操作不能和读操作同时进行。
struct ThreadSafe { mutable std::shared_timed_mutex _mutex; int _value; ThreadSafe() { _value = 0; } int get() const { std::shared_lock<std::shared_timed_mutex> loc(_mutex); return _value; } void increase() { std::unique_lock<std::shared_timed_mutex> lock(_mutex); _value += 1; } };
#include <array> #include <iostream> #include <tuple> #include <utility> template <typename T, T... ints> void print_sequence(std::integer_sequence<T, ints...> int_seq) { std::cout << "The sequence of size " << int_seq.size() << ": "; ((std::cout << ints << ' '), ...); std::cout << '\n'; } // 转换数组为 tuple template <typename Array, std::size_t... I> auto a2t_impl(const Array &a, std::index_sequence<I...>) { return std::make_tuple(a[I]...); } template <typename T, std::size_t N, typename Indices = std::make_index_sequence<N>> auto a2t(const std::array<T, N> &a) { return a2t_impl(a, Indices{}); } // 漂亮地打印 tuple template <class Ch, class Tr, class Tuple, std::size_t... Is> void print_tuple_impl(std::basic_ostream<Ch, Tr> &os, const Tuple &t, std::index_sequence<Is...>) { ((os << (Is == 0 ? "" : ", ") << std::get<Is>(t)), ...); } template <class Ch, class Tr, class... Args> auto &operator<<(std::basic_ostream<Ch, Tr> &os, const std::tuple<Args...> &t) { os << "("; print_tuple_impl(os, t, std::index_sequence_for<Args...>{}); return os << ")"; } int main() { print_sequence(std::integer_sequence<unsigned, 9, 2, 5, 1, 9, 1, 6>{}); print_sequence(std::make_integer_sequence<int, 20>{}); print_sequence(std::make_index_sequence<10>{}); print_sequence(std::index_sequence_for<float, std::iostream, char>{}); std::array<int, 4> array = {1, 2, 3, 4}; // 转换 array 为 tuple auto tuple = a2t(array); static_assert(std::is_same<decltype(tuple), std::tuple<int, int, int, int>>::value, ""); // 打印到 cout std::cout << tuple << '\n'; }
#include <iostream> #include <utility> #include <vector> using namespace std; int main() { vector<int> vec1{1, 2, 3, 4}; vector<int> vec2{5, 6, 7, 8}; cout << "exchange before: " << endl; cout << "vec1: " << endl; copy(vec1.begin(), vec1.end(), ostream_iterator<int>{cout, " "}); cout << endl << "vec2: " << endl; copy(vec2.begin(), vec2.end(), ostream_iterator<int>{cout, " "}); exchange(vec1, vec2); cout << endl << "exchange after: " << endl; cout << "vec1: " << endl; copy(vec1.begin(), vec1.end(), ostream_iterator<int>{cout, " "}); cout << endl << "vec2: " << endl; copy(vec2.begin(), vec2.end(), ostream_iterator<int>{cout, " "}); return 0; }
MSVC编译器的实现:
// FUNCTION TEMPLATE exchange
template <class _Ty, class _Other = _Ty>
_CONSTEXPR20 _Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept(
conjunction_v<is_nothrow_move_constructible<_Ty>, is_nothrow_assignable<_Ty&, _Other>>) /* strengthened */ {
// assign _New_val to _Val, return previous _Val
_Ty _Old_val = static_cast<_Ty&&>(_Val);
_Val = static_cast<_Other&&>(_New_val);
return _Old_val;
}
#include <iomanip>
#include <iostream>
#include <string>
int main() {
std::string str{"hello world"};
std::cout << str << std::endl; // hello world
std::cout << std::quoted(str) << std::endl; // "hello world"
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。