C++常用特性

C++常用特性,持续更新……

1. std::for_each()、std::mem_fn()

#include <algorithm>  // std::for_each
#include <functional> // std::mem_fn
#include <iostream>
#include <vector>
#include <thread>

struct MfFe
{
	int m_a;
	int m_b;

	int sum(int i, int j)
	{
		return i + j;
	}

	int tuple(int i)
	{
		return i*3;
	}
};

int square(int i)
{
	std::cout << i * i << std::endl;
	return i * i;
}

int multiply(int i,int j)
{
	std::cout << i * j << std::endl;
	return i * j;
}

int main()
{
	std::vector<std::thread> vecth;
	for (int i = 0; i!=10; ++i)
	{
		vecth.push_back(std::thread(multiply,i,i+1));
	}
	std::for_each(vecth.begin(), vecth.end(), std::mem_fn(&std::thread::join));

	/* 在std::for_each中调用square */
	std::vector<int> avec;
	for (int i = 0; i!=10;++i)
	{
		avec.push_back(i);
	}
	/* 解引avec.begin()作为square的参数 */
	std::for_each(avec.begin(), avec.end(), square);

	/* 此处不能模仿L42的用法使用std::mem_fn(&MfFe::tuple),因此下面这句是错误的 */
	//std::for_each(avec.begin(), avec.end(), std::mem_fn(&MfFe::tuple));

	/* 使用std::mem_fn进行函数调用,std::mem_fn的参数必须是类函数 */
	MfFe amf{ 1,2 };
	auto fn = std::mem_fn(&MfFe::sum);
	std::cout << fn(amf, amf.m_a, amf.m_b) << std::endl;

	system("pause");
}

另一个简明的例子:

// for_each example
#include <iostream>     // std::cout
#include <algorithm>    // std::for_each
#include <vector>       // std::vector
int main() {
	std::vector<int> myvector({10,20,30});
    /* 运行时myvector的迭代器解引用后赋给i */
	std::for_each(myvector.cbegin(), myvector.cend(), [](int i){std::cout << i << " "; });

	std::cout << '\n';
}

输出结果:10 20 30

2. std::allocator

示例1:

#include <memory>
#include <iostream>
#include <string>

int main(){
	std::allocator<std::string> alloc;
	const int num = 5;
	std::string *pstr = alloc.allocate(num);
	std::string *pbegin = pstr;
	for (int i = 0; i != num; ++i)
	{
		alloc.construct(pstr++,std::to_string(i));
	}
	while (pstr!=pbegin)
	{
		std::cout << *(--pstr) << "  ";
	}
	for (int i = 0; i != num; ++i)
	{
		alloc.destroy(pstr++);
	}
	alloc.deallocate(pbegin, num);

	std::cout << std::endl;
	system("pause");
}

输出结果为:4 3 2 1 0
示例2:

/* 消除std::uninitialized_copy()编译时报的错误 */
#pragma warning(disable:4996)

#include <memory>
#include <iostream>
#include <string>
#include <vector>

int main(){
	std::allocator<std::string> alloc;
	std::vector<std::string> avec{ "Ambarella", "HISI", "Seagate", "Intelli-Vision", "Novatek" };

	std::string *pstr = alloc.allocate(avec.size()*2);
	/* std::uninitialized_copy()返回(递增后的)目的位置迭代器,
	   因此,一次std::uninitialized_copy()调用会返回一个指针,
	   指向最后一个构造的元素之后的位置。 */
	auto q = std::uninitialized_copy(avec.begin(), avec.end(), pstr);
	std::uninitialized_fill_n(q, avec.size(), "ARM");
	for (int i = 0; i != avec.size() * 2; ++i)
	{
		std::cout << pstr[i] << "  ";
	}
	std::cout << std::endl;
	system("pause");
}

输出结果:Ambarella HISI Seagate Intelli-Vision Novatek ARM ARM ARM ARM ARM

3. std::uninitialized_fill、std::uninitialized_fill_n、std::uninitialized_copy、std::uninitialized_copy_n

std::uninitialized_fill()原型:
template <class ForwardIterator, class T> void uninitialized_fill (ForwardIterator first, ForwardIterator last, const T& x);
作用:Fill block of memory. Constructs all the elements in the range [first,last) initializing them to a value of x.`

#include <memory>
#include <vector>
#include <iostream>
int main(){
	std::vector<int> avec;
	avec.resize(10);
	/* std::uninitialized_fill()没有返回值 */
	std::uninitialized_fill(avec.begin(), avec.end(), 5);
	for (auto const &it : avec)
	{
		std::cout << it << "  ";
	}
	std::cout << std::endl;
}

std::uninitialized_fill_n()原型:
template <class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n (ForwardIterator first, Size n, const T& x);
作用:Fill block of memory. Constructs n elements in the array pointed by first, initializing them to a value of x.

#include <memory>
#include <vector>
#include <iostream>
int main(){
	std::vector<int> avec;
	avec.resize(10);
	/* std::uninitialized_fill_n()返回添加的最后一个元素后面的迭代器 */
	auto it = std::uninitialized_fill_n(avec.begin(), 5, 1);
	//std::uninitialized_fill(avec.begin() + 5, avec.end(), 2);
	std::uninitialized_fill(it, avec.end(), 2);

	for (auto const &it : avec)
	{
		std::cout << it << "  ";
	}
	std::cout << std::endl;
}

std::uninitialized_copy()原型:
template <class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy ( InputIterator first, InputIterator last, ForwardIterator result );
作用:Copy block of memory. Constructs copies of the elements in the range [first,last) into a range beginning at result and returns an iterator to the last element in the destination range.

#pragma warning(disable:4996)
#include <memory>
#include <iostream>
#include <vector>
int main()
{
	std::vector<int> avec{0,1,2,3,4,5,6,7,8,9};

	std::allocator<int> alloc;
	int *pi = alloc.allocate(avec.size());
	/* 先拷贝前五个元素,返回值迭代器it目前指向pi的第六个元素 */
	auto it = std::uninitialized_copy(avec.begin(), avec.end()-5, pi);
	/* 再拷贝后五个元素,拷贝的起始位置是迭代器it */
	std::uninitialized_copy_n(avec.end() - 5, 5, it);
	for (int i = 0; i != avec.size(); ++i)
	{
		std::cout << pi[i] << "  ";
	}
	std::cout << std::endl;

	system("pause");
}

std::uninitialized_copy_n的原型:
template <class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n ( InputIterator first, Size n, ForwardIterator result );
作用:Copy block of memory. Constructs copies of the n first elements of the array pointed by first into a range beginning at result and returns an iterator to the last element in the destination range.

#pragma warning(disable:4996)
#include <iostream>
#include <memory>
#include <vector>
int main(){
	std::vector<int> avec{0,1,2,3,4,5,6,7,8,9};
	std::allocator<int> alloc;
	int *pi = alloc.allocate(avec.size());
	/* 先拷贝avec的前五个元素,返回值迭代器it目前指向pi的第六个元素的位置 */
	auto it = std::uninitialized_copy_n(avec.begin(), avec.size()-5, pi);
	/* 再拷贝avec的后五个元素,拷贝的起始位置是it */
	std::uninitialized_copy(avec.end() - 5, avec.end(), it);
	for (int i = 0; i != avec.size(); ++i)
	{
		std::cout << pi[i] << "  ";
	}
	std::cout << std::endl;
	system("pause");
}

4. 标准库特殊设施

4.1 tuple

使用示例:

#include <iostream>
#include <tuple>
#include <vector>
#include <string>
#include <typeinfo>

int main() {
	std::tuple<std::string, int, double> tubook1;
	std::tuple<std::string, int, double> tubook2("Principle", 3, 60.8);
	std::tuple<int, int, int> tubook3(1, 3, 2);
	auto tu = std::make_tuple("Principle", 3, 60.8f, std::vector<int>{1,2,3});

	/* 只可比较成员数量相同的tuple,并且对每对成员使用比较运算符都是合法的,
	   比较可以是==,!=,<,>,>=等 */
	auto cp1 = (tubook1 == tubook2);
	std::cout << cp1 << std::endl;  // 输出:0

	/* 下面注释的两句,无法通过编译,因为tuple的成员数量不相同 */
	// auto cp2 = (tubook2 == tu);
	// std::cout << cp2 << std::endl;

	/* 下面注释的两句,无法通过编译,因为tuple的第一对对应的成员一个是string,一个是int无法进行比较 */
	// auto cp3 = (tubook2 == tubook3);
	// std::cout << cp3 << std::endl;

	/* 输出tu类型的tuple成员数量 */
	std::cout << std::tuple_size<decltype(tu)>::value << std::endl;  // 输出:4

	/* 输出tu类型的第2个成员的类型 */
	std::cout << typeid(std::tuple_element<2, decltype(tu)>::type).name() << std::endl;  // 输出:float

	/* 输出tubook2的第1个元素 */
	std::cout << std::get<0>(tubook2) << std::endl;  // 输出:Principle
}

使用tuple返回多个值:

#include <iostream>
#include <tuple>
#include <vector>
#include <string>
#include <typeinfo>

std::tuple<std::string, int> func(std::string strArithmetic, int num1,int num2) {
	if ("+" == strArithmetic)
	{
		return std::make_tuple("+", num1 + num2);
	}
	else if ("-" == strArithmetic)
	{
		return std::make_tuple("-", num1 - num2);
	}
	else if ("*" == strArithmetic)
	{
		return std::make_tuple("*", num1 * num2);
	}
	else if ("/" == strArithmetic)
	{
		if (0 == num2)
		{
			return std::make_tuple("division by zero", 0);
		}
		return std::make_tuple("/", num1 / num2);
	}
	else
	{
		return std::make_tuple("illegal operation", 0);
	}
}

int main() {
	std::string strop("/");
	int a = 20;
	int b = 5;

	auto ret = func(strop, a, b);

	/* 输出结果:operation: /, result: 4 */
	std::cout << "operation: " << std::get<0>(ret) << ", result: " << std::get<1>(ret) << std::endl;
}

4.2 bitset

构造函数:

constexpr bitset() noexcept;

constexpr bitset (unsigned long long val) noexcept;

template <class charT, class traits, class Alloc>
  explicit bitset (const basic_string<charT,traits,Alloc>& str,
    typename basic_string<charT,traits,Alloc>::size_type pos = 0,
    typename basic_string<charT,traits,Alloc>::size_type n =
      basic_string<charT,traits,Alloc>::npos,
    charT zero = charT('0'), charT one = charT('1'));
    
template <class charT>
  explicit bitset (const charT* str,
    typename basic_string<charT>::size_type n = basic_string<charT>::npos,
    charT zero = charT('0'), charT one = charT('1'));

示例:

#include <bitset>
#include <string>
#include <iostream>

int main() {
    std::bitset<13> bitvec1(0xf);   // 0 0000 0000 1111
    std::bitset<3> bitvec2(0xf);    // 111
    std::bitset<128> bitvec3(~0ULL);// 0-63位为1;63-127位为0

    std::bitset<8>bitvec4(std::string("9991"),0,std::string::npos,'1','9'); // 0000 1110
    std::bitset<8>bitvec5("9991", std::string::npos, '1', '9'); // 0000 1110
    std::bitset<8>bitvec6("10010");  // 0001 0010

    std::cout << bitvec1.count() << std::endl;  // 4
    std::cout << bitvec3.count() << std::endl;  // 64
    std::cout << bitvec6.count() << std::endl;  // 2

    std::cout << bitvec6.any() << " " << bitvec6.all() << " " << bitvec6.none() << std::endl; // 1 0 0
    std::cout << bitvec3.size() << std::endl;  // 128

    std::cout << bitvec1 << std::endl;  // 0 0000 0000 1111
    bitvec1.flip();
    std::cout << bitvec1 << std::endl;  // 1 1111 1111 0000

    unsigned long ulong = bitvec2.to_ulong();
    std::cout << "ulong = " << ulong << std::endl;  // 输出: ulong = 7
}

4.3 regular expression

4.4 random-number

4.5 禁止拷贝构造函数、禁止拷贝赋值运算符

// Disable the copy and assignment operator for a class.
#define DISABLE_COPY_AND_ASSIGN(classname) \
private:\
  classname(const classname&);\
  classname& operator=(const classname&)

4.6 std::unique_ptr自动释放内存

int main() {
    auto lambdaDeleter=[](int *p){
        delete p; p = nullptr;
        printf("1-----> p = %p(Self-define deleter called.)\n", p);
    };
    for (int i = 0; i < 20; ++i) {
        std::unique_ptr<int, decltype(lambdaDeleter)> uniPtr(new int, lambdaDeleter);  // 每次运行到这里会释放之前的内存,申请新内存
        printf("0-----> uniPtr.get() = %p\n", uniPtr.get());
    }
}

输出:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值