c++高级用法
lambda函数的两种用法
-
lambda标准语法
-
auto
auto factorial = [](auto self, int n) -> int {
return n < 2 ? 1 : n * self(self, n - 1);
};
- function
std::function<void(int, int)> dfs = [&](int i, int j) {
if (mask_.at<uchar>(i, j) == 255) return;
mask_.at<uchar>(i, j) = 255;
for (int k = 0; k < 4; ++k)
{
int ii = i + ff[k][0], jj = j + ff[k][1];
if (ii < m.rows && jj < m.cols)
dfs(ii, jj);
}
};
- 如果文件存在,删除文件
#ifdef _WIN32
#include <io.h>
#include <cstdio>
#endif
#ifdef linux
#include <unistd.h>
#include <fcntl.h>
#endif
void delete_file(std::string strFileName){
#ifdef linux
if (access(strFileName.c_str(), F_OK) == 0)
remove(strFileName.c_str());
#endif
#ifdef _WIN32
if (_access(strFileName.c_str(), 0) == 0)
remove(strFileName.c_str());
#endif
}
goto
- a的值等于15时,程序会跳过迭代并继续执行下一次循环
LOOP:do {
if( a == 15) {
// 跳过迭代
a = a + 1;
goto LOOP;
}
其他编译单元就可以直接调用
__attribute__((visibility("default")))
测试
boost.cpp
#include <boost/test/included/unit_test.hpp>
#include "need2test.h"
#include "need2test2.h"
need2test.h
#define BOOST_TEST_MODULE MyTestModule
BOOST_AUTO_TEST_SUITE(MyTestSuite)
BOOST_AUTO_TEST_CASE(MyTestCase1)
{
BOOST_CHECK(1 + 1 == 2);
}
BOOST_AUTO_TEST_CASE(MyTestCase2)
{
BOOST_CHECK(2 * 2 == 4);
}
BOOST_AUTO_TEST_SUITE_END()
-std=c++11
禁止对象的拷贝与赋值delete
struct A {
A() = default;
A(const A&) = delete;
A& operator=(const A&) = delete;
int a;
A(int i) { a = i; }
};
int main() {
A a1;
A a2 = a1; // 错误,拷贝构造函数被禁用
A a3;
a3 = a1; // 错误,拷贝赋值操作符被禁用
}
-std=c++14
C++14引入了二进制字面量,也引入了分隔符
int a = 0b0001'0011'1010;
double b = 3.14'1234'1234'1234;
std::make_unique
struct A {};
std::unique_ptr<A> ptr = std::make_unique<A>();
多读、单写锁
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;
}
};
std::exchange比swap更高效
std::vector<int> v;
std::exchange(v, {1,2,3,4});
std::quoted 给字符串添加双引号
cout << std::quoted(str) << endl;
"hello world"
inline
允许同一个函数或变量的定义出现在多个编译单元中
//a.h
inline void func();
//b.h
#include "a.h"
inline void func();
-std=c++17
构造函数模板推导
pair<int, double> p(1, 2.2); // before c++17
pair p(1, 2.2); // c++17 自动推导
vector v = {1, 2, 3}; // c++17
结构化绑定
std::tuple<int, double> func() {
return std::tuple(1, 2.2);
}
int main() {
auto[i, d] = func(); //是C++11的tie吗?更高级
cout << i << endl;
cout << d << endl;
}
折叠表达式
template <typename ... Ts>
auto sum(Ts ... ts) {
return (ts + ...);
}
int a {sum(1, 2, 3, 4, 5)}; // 15
std::string a{"hello "};
std::string b{"world"};
cout << sum(a, b) << endl; // hello world
C++17引入了constexpr lambda表达式,可以用于在编译期进行计算。
有以下限制
函数体不能包含汇编语句goto语句、label、try块、静态变量、线程局部存储、
没有初始化的普通变量,不能动态分配内存,不能有new delete等,
不能虚函数
int main() { // c++17可编译
constexpr auto lamb = [] (int n) { return n * n; };
static_assert(lamb(3) == 9, "a");
}
namespace嵌套
namespace A {
namespace B {
namespace C {
void func();
}
}
}
// c++17,更方便更舒适
namespace A::B::C {
void func();)
}
__has_include预处理表达式
#if defined __has_include
#if __has_include(<charconv>)
#define has_charconv 1
#include <charconv>
#endif
#endif
std::optional<int> ConvertToInt(const std::string& str) {
int value{};
#ifdef has_charconv
const auto last = str.data() + str.size();
const auto res = std::from_chars(str.data(), last, value);
if (res.ec == std::errc{} && res.ptr == last) return value;
#else
// alternative implementation...
其它方式实现
#endif
return std::nullopt;
}
std::variant
类似union的功能,但比union更高级
int main() { // c++17可编译
std::variant<int, std::string> var("hello");
cout << var.index() << endl;
var = 123;
cout << var.index() << endl;
try {
var = "world";
std::string str = std::get<std::string>(var); // 通过类型获取值
var = 3;
int i = std::get<0>(var); // 通过index获取对应值
cout << str << endl;
cout << i << endl;
} catch(...) {
// xxx;
}
return 0;
}
std::optional
- 让函数返回对象指针,异常情况下返回nullptr
std::optional<int> StoI(const std::string &s) {
try {
return std::stoi(s);
} catch(...) {
return std::nullopt;
}
}
void func() {
std::string s{"123"};
std::optional<int> o = StoI(s);
if (o) {
cout << *o << endl;
} else {
cout << "error" << endl;
}
}
std::any
C++17引入了any可以存储任何类型的单个值
int main() { // c++17可编译
std::any a = 1;
cout << a.type().name() << " " << std::any_cast<int>(a) << endl;
a = 2.2f;
cout << a.type().name() << " " << std::any_cast<float>(a) << endl;
if (a.has_value()) {
cout << a.type().name();
}
a.reset();
if (a.has_value()) {
cout << a.type().name();
}
a = std::string("a");
cout << a.type().name() << " " << std::any_cast<std::string>(a) << endl;
return 0;
}
std::string_view
if-switch语句初始化
// if (init; condition)
if (int a = GetValue()); a < 101) {
cout << a;
}
string str = "Hi World";
if (auto [pos, size] = pair(str.find("Hi"), str.size()); pos != string::npos) {
std::cout << pos << " Hello, size is " << size;
}
折叠表达式
template <typename ... Ts>
auto sum(Ts ... ts) {
return (ts + ...);
}
int a {sum(1, 2, 3, 4, 5)}; // 15
std::string a{"hello "};
std::string b{"world"};
cout << sum(a, b) << endl; // hello world
新增Attribute
- [[fallthrough]],用在switch中提示可以直接落下去,不需要break,让编译期忽略警告
- [[nodiscard]] :表示修饰的内容不能被忽略,可用于修饰函数,标明返回值一定要被处理
- [[maybe_unused]] :提示编译器修饰的内容可能暂时没有使用,避免产生警告
C++17使用as_const可以将左值转成const类型
std::string str = "str";
const std::string& constStr = std::as_const(str);
-std=c++20
默认生成一系列的比较运算符
即:==,!=,<,>,<=,>=
自定义时有三种可用的返回类型:
- std::strong_ordering:强比较,严格按照比较的顺序、方式来进行,不能从下面两个转回,特别注意的是它不区分等价值。
- std::weak_ordering:弱比较,对比较的大小写,可以对等价的字符串用某种方式区别
- std::partial_ordering:偏序比较,其实就是自定义,把直观上不可能比较的对象通过某种方式来进行比较
auto operator<=>(const Point&) const = default;
class TotallyOrdered : Base {
std::string tax_id;
std::string first_name;
std::string last_name;
public:
TotallyOrdered(const std::string& id, const std::string& first, const std::string& last)
:tax_id(id), first_name(first), last_name(last) {}
// 定制 operator<=>,因为我们想先比较姓
std::strong_ordering operator<=>(const TotallyOrdered& that) const {
if (auto cmp = (Base&)(*this) <=> (Base&)that; cmp != 0) return cmp;
if (auto cmp = last_name <=> that.last_name; cmp != 0) return cmp;
if (auto cmp = first_name <=> that.first_name; cmp != 0) return cmp;
return tax_id <=> that.tax_id;
}
// ……非比较函数……
};
constexpr std::weak_ordering operator<=>(Rational_2 lhs, Rational_2 rhs)
{
return lhs.num * rhs.den <=> rhs.num * lhs.den;
}
模板
- 可以使用省略号运算符 (...) 定义采用任意数量的零个或多个类型参数的模板:
template<typename... Arguments> class vtclass;
vtclass< > vtinstance1;
vtclass<int> vtinstance2;
vtclass<float, bool> vtinstance3;
- C++ 模板支持非类型参数,也称为值参数
- size_t 值在编译时作为模板参数传入,必须是 const 或 constexpr 表达式。
template<typename T, size_t L>
class MyArray
{
T arr[L];
public:
MyArray() { ... }
};
MyArray<MyClass*, 10> arr;
- 模板作为模板参数
template<typename T, template<typename, int> class Arr>
class MyClass2
{
T t; //OK
Arr<T, 10> a;
};
- 默认模板自变量
template<typename A = int, typename B = double>
class Bar
{
//...
};
...
int main()
{
Bar<> bar; // use all default type arguments
}
- 例如,std::vector 模板有一个用于分配器的默认自变量:
template <class T, class Allocator = allocator<T>> class vector;
本文来自博客园,作者:InsiApple,转载请注明原文链接:https://www.cnblogs.com/InsiApple/p/17295397.html