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());
}
}
输出: