C++11相关应用总结:

一、 C++11原子操作

Lock-Free 编程

示例代码

// atomic::compare_exchange_weak example:
#include <iostream>       // std::cout
#include <atomic>         // std::atomic
#include <thread>         // std::thread
#include <vector>         // std::vector

// a simple global linked list:
struct Node { int value; Node* next; };
std::atomic<Node*> list_head (nullptr);

void append (int val) {     // append an element to the list
  Node* oldHead = list_head;
  Node* newNode = new Node {val,oldHead};

  // what follows is equivalent to: list_head = newNode, but in a thread-safe way:
  while (!list_head.compare_exchange_weak(oldHead,newNode))
    newNode->next = oldHead;
}

int main ()
{
  // spawn 10 threads to fill the linked list:
  std::vector<std::thread> threads;
  for (int i=0; i<10; ++i) threads.push_back(std::thread(append,i));
  for (auto& th : threads) th.join();

  // print contents:
  for (Node* it = list_head; it!=nullptr; it=it->next)
    std::cout << ' ' << it->value;
  std::cout << '\n';

  // cleanup:
  Node* it; while (it=list_head) {list_head=it->next; delete it;}

  return 0;
}

参考文档

  1. msdn社区介绍
  2. 类型详解二 std::atomic
  3. C++11中的原子操作(atomic operation)
  4. C++并发实战16: std::atomic原子操作

二、 C++11多线程

参考文档

  1. C++11 多线程初探
  2. C++11 multithreading tutorial
  3. C++官网:multithreading相关类介绍
  4. C++11 run templated class function with std::thread
  5. C++ std::thread of a member function
  6. shared_ptr和多线程
  7. C++开发:为什么多线程读写shared_ptr要加锁的详细介绍

实例

Thread.h

#ifndef __THREAD_H__
#define __THREAD_H__

#include <thread>
#include <memory>

class Thread {
public:
	virtual ~Thread() {}
	void start(std::shared_ptr<Thread> ptr);

protected:
	virtual void run() {}

private:
	static void invoke(std::shared_ptr<Thread> ptr);
};

#endif //__THREAD_H__

Thread.cpp

#include "Thread.h"

void Thread::start(std::shared_ptr<Thread> ptr) {
	if (this == ptr.get()) {
		std::thread thd(Thread::invoke, ptr);
		thd.detach();
	}
}

void Thread::invoke(std::shared_ptr<Thread> ptr) {
	if (ptr) {
		ptr->run();
	}
}

main.cpp

#include <atomic>
#include "Thread.h"

class TestThread : public Thread {
public:
	TestThread(int count) : m_count(count) {}
	int reduce();

protected:
	virtual void run();

private:
	std::atomic<int> m_count;
};

int TestThread::reduce() {
	return --m_count;
}

void TestThread::run() {
	while (m_count > 0) {
		m_count--;
	}
}

int main() {
	for (int i = 0; i < 1000; i++) {
		std::shared_ptr<Thread> sp(new TestThread(1000));
		sp->start(sp);
		
		std::shared_ptr<TestThread> tsp = std::dynamic_pointer_cast<TestThread>(sp);
		if (tsp) {
			while (tsp->reduce() > 0);
		}
	}
	return 0;
}

shared_from_this优化版本:

#include <thread>
#include <memory>
#include <atomic>

class Thread : public std::enable_shared_from_this<Thread> {
public:
    void start();

protected:
	virtual ~Thread() {}
    virtual void run() {};
};

void Thread::start() {
	auto ptr(shared_from_this());
	if (ptr) {
		std::thread thd([ptr]() {
			ptr->run();
		});
		thd.detach();
	}
}

class TestThread : public Thread {
public:
    TestThread(int count) : m_count(count) {}
    int reduce();

protected:
    virtual void run();

private:
    std::atomic<int> m_count;
};

int TestThread::reduce() {
    return --m_count;
}

void TestThread::run() {
    while (m_count > 0) {
        m_count--;
    }
}

int main() {
    for (int i = 0; i < 1000; i++) {
        std::shared_ptr<Thread> sp(new TestThread(1000));
        sp->start();

        std::shared_ptr<TestThread> tsp = std::dynamic_pointer_cast<TestThread>(sp);
        if (tsp) {
            while (tsp->reduce() > 0);
        }
    }
    return 0;
}

参考文档Boost 库 Enable_shared_from_this 实现原理分析

普通使用的优化版本:

#include <thread>
#include <memory>
#include <atomic>

class Thread : public std::enable_shared_from_this<Thread> {
public:
    void start();

protected:
    virtual ~Thread() {}
    virtual void run() {};
};

void Thread::start() {
    auto ptr(shared_from_this());
    if (ptr) {
	std::thread thd([ptr]() {
	    ptr->run();
	});
	thd.detach();
    }
}

class TestThread : public Thread {
public:
    TestThread(int count) : m_count(count) {}
    ~TestThread() { std::cout << __FUNCTIONW__ << std::endl; }
    int reduce();

protected:
    virtual void run();

private:
    std::atomic<int> m_count;
};

int TestThread::reduce() {
    return --m_count;
}

void TestThread::run() {
    while (m_count > 0) {
        m_count--;
    }
}

int main() {
    std::make_shared<TestThread>(1000)->start();
    //TODO main loop
    return 0;
}

注释:

  1. std::thread类对象thd释放,线程函数不受影响,继续执行。
  2. TestThread的实例化在主线程执行,实例化对象的释放在子线程执行。

3.0 C++11智能指针shared_ptr的简单实现

#ifndef _SMART_PTR_
#define _SMART_PTR_

template <class _Ty>
struct inner_ptr {
	inner_ptr(_Ty* ptr, int cnt) : rawPtr(ptr), count(cnt) {}
	~inner_ptr() {
		if (rawPtr != nullptr) 
			delete rawPtr;
	}
	_Ty* rawPtr;
	int count;
};

template <class _Ty>
class smart_ptr {
private:
	typedef struct inner_ptr<_Ty> Iy;
	Iy* iyPtr;

public:
	smart_ptr(_Ty* ptr = nullptr) {
		iyPtr = nullptr;
		if (ptr != nullptr)
			iyPtr = new Iy(ptr, 1);
	}

	smart_ptr(const smart_ptr<_Ty>& other) {
		if (other.iyPtr != nullptr) {
			iyPtr = other.iyPtr;
			iyPtr->count++;
		} else {
			iyPtr = nullptr;
		}
	}

	~smart_ptr() {
		if (iyPtr != nullptr)
			if (--(iyPtr->count) == 0)
				delete iyPtr;
	}

	const smart_ptr<_Ty>& operator=(const smart_ptr<_Ty>& other) {
		if (iyPtr == other.iyPtr)
			return (*this);

		if (iyPtr != nullptr)
			if (--(iyPtr->count) == 0)
				delete iyPtr;

		if (other.iyPtr != nullptr) {
			iyPtr = other.iyPtr;
			iyPtr->count++;
		} else {
			iyPtr = nullptr;
		}

		return (*this);
	}

	_Ty* operator->() const {
		if (iyPtr != nullptr)
			return iyPtr->rawPtr;
		else
			return nullptr;
	}

	int use_count() const {
		if (iyPtr != nullptr) 
			return iyPtr->count;
		else 
			return 0;
	}
};

#endif //_SMART_PTR_
void main(int argc, char **argv) {
	...
	{
		smart_ptr<Copy> spr1;
		{
			smart_ptr<Copy> spr(new Copy(236));
			spr->print();
			spr1 = spr;
		}
		spr1->print();
	}
	...
}

上述实现和std::shared_ptr的区别:

1st. 引用计数(_Uses and _Weaks)封装成单独类_Ref_count_base

class _Ref_count_base
{	// common code for reference counting
private:
	virtual void _Destroy() = 0;
	virtual void _Delete_this() = 0;

private:
	_Atomic_counter_t _Uses;
	_Atomic_counter_t _Weaks;

2nd. std::shared_ptr的基类_Ptr_base封装有_Ty *_Ptr(raw pointer)和_Ref_count_base指针

// TEMPLATE CLASS _Ptr_base
template<class _Ty>
class _Ptr_base
{	// base class for shared_ptr and weak_ptr
private:
	_Ty *_Ptr;
	_Ref_count_base *_Rep;

可以理解为:通过std::shared_ptr<_Ty> sp(new _Ty) or std::make_shared<_Ty>(new _Ty), _Ty对象会关联相应的引用计数.

===============================

以下延伸:

//////////////pay attention/////////////
Msg* pMsg = new Msg("hello001");
std::shared_ptr<Msg> sp001(pMsg);
std::shared_ptr<Msg> sp002(pMsg);
std::cout << sp001.use_count() << std::endl; // print 1
std::cout << sp002.use_count() << std::endl; // print 1
//////////////pay attention/////////////

需要注意:每次执行std::shared_ptr<Msg> sp(pMsg)都会为Msg对象创建_Ref_count_base对象(包含引用计数),所以会导致Msg对象的释放错误.

3.1 C++11智能指针shared_ptr

利用shared_ptr实现消息队列的简单实现:

#include <deque>
#include <memory>
#include <string>
#include <functional>

class Msg : public std::enable_shared_from_this<Msg> {
public:
	Msg(const std::string& data) : m_data(data) {}
	~Msg() { std::cout << "Msg::~Msg" << std::endl; }

	std::function<const std::string& ()> registerCallback() {

		std::shared_ptr<Msg> self(shared_from_this());

		std::function<const std::string& ()> functor = [this, self]() -> const std::string& {
			return m_data;
		};

		return functor;
	}
private:
	std::string m_data;
};

int main(int argc, char **argv) {

	std::deque<std::function<const std::string& ()>> msgque;

	for (int i=1; i<=10; i++) {
		std::string data = std::string("message").append(std::to_string(i));
		std::shared_ptr<Msg> sp = std::make_shared<Msg>(data);
		msgque.push_back(sp->registerCallback());
	}

#if 1
	while (!msgque.empty()) {
		auto functor = msgque.front();
		msgque.pop_front();
		std::string data = functor();
		std::cout << "process: " << data << std::endl;
	}
#else
	std::for_each(msgque.begin(), msgque.end(),
		[](const std::function<const std::string& ()>& callback) {
			std::string data = callback();
			std::cout << "process: " << data << std::endl;
	});
	msgque.clear();
#endif

	return 0;
}

用例说明:

  1. 通过继承std::enable_shared_from_this实现消息Msg的封装。
  2. 将封装有Msg对象指针(this)及智能指针(shared_ptr<Msg> self)的消息处理函数(std::function<const std::string& ()>对象)添加到消息队列。
  3. 当消息队列中的消息处理函数释放时,消息处理函数封装的智能指针释放,智能指针所指向的Msg对象的引用计数为0,Msg对象释放。

注:使用std::shared_ptr<Msg> self(shared_from_this())而不直接使用std::shared_ptr<Msg> self(this)的原因参考3.0的最后注意事项.

参考文档

  1. C++ 智能指针类
  2. C++11中的智能指针
  3. Boost 库 Enable_shared_from_this 实现原理分析

===============================

使用std::shared_ptr<_Ty> & std::enable_shared_from_this<_Ty>的思路:

需要用到异步事件处理的场景。先将事件相关信息封装成类,将事件处理函数以lambda形式通过在事件类内实现而完成注册,且lambda函数通过shared_from_this()初始化的std::shared_ptr管理事件类对象的生存周期。可以理解为事件类对象封装到事件处理回调函数(std::function)。程序注册事件处理函数后,立即返回,待事件触发后调用相关事件处理回调函数。当事件处理回调函数释放时,其管理的事件类对象释放。

事件处理函数(lambda)封装事件对象this指针和指向该事件对象的std::shared_ptr,在lambda函数内可以通过this指针按照事件类内调用原则进行调用,可以通过调用虚函数实现一定程度的扩展。

3.2 C++11智能指针weak_ptr

std::shared_ptr<int> sp1,sp2;
std::weak_ptr<int> wp, wp2;

sp1 = std::make_shared<int> (20);    // sp1
wp = sp1;                            // sp1, wp
std::cout << wp.use_count() << std::endl;
std::cout << sp1.use_count() << std::endl;

sp2 = wp.lock();                     // sp1, wp, sp2
sp1.reset();                         //      wp, sp2
wp2 = wp;
std::cout << wp.use_count() << std::endl;
std::cout << sp2.use_count() << std::endl;

if (!sp1) {
	sp1 = wp.lock();             // sp1, wp, sp2
}

std::cout << "*sp1: " << *sp1 << '\n';
std::cout << "*sp2: " << *sp2 << '\n';

参考文档Boost 库 Enable_shared_from_this 实现原理分析

四、 右值引用 T&&

class Mem {
public:
	~Mem();
	Mem() : m_str(nullptr), m_len(0) {}
	Mem(const char* str, int len);
	Mem(const Mem& obj);
	Mem(Mem&& obj);
	Mem& operator=(Mem&& obj);
private:
	int m_len;
	char* m_str;
};

Mem::~Mem() {
	if (m_str != nullptr) {
		delete[] m_str;
	}
}

Mem::Mem(const char* str, int len) {
	m_str = new char[len + 1];
	memcpy(m_str, str, len);
	m_str[len] = '\0';
	m_len = len;
}

Mem::Mem(const Mem& obj) {
	m_str = new char[obj.m_len + 1];
	memcpy(m_str, obj.m_str, obj.m_len);
	m_str[obj.m_len] = '\0';
	m_len = obj.m_len;
}

// move construction
Mem::Mem(Mem&& obj) {
	m_str = obj.m_str;
	m_len = obj.m_len;
	obj.m_str = nullptr;
	obj.m_len = 0;
}

// move assignment operator
Mem& Mem::operator=(Mem&& obj) {
	std::swap(m_str, obj.m_str);
	std::swap(m_len, obj.m_len);
	return (*this);
}

void main() {
	std::list<Mem> mlist;
	mlist.push_back(std::move(Mem("hello", strlen("hello")))); // call move construction
	mlist.push_back(std::move(Mem("world", strlen("world"))));
	
	std::map<int, Mem> mp;
	mp[0] = std::move(lsclone::Mem("hello", strlen("hello"))); // call move assignment operator
	mp[1] = std::move(lsclone::Mem("world", strlen("world")));
}

说明:

五、auto关键字

1、 auto不能用来声明函数的返回值。但如果函数有一个尾随的返回类型时,auto是可以出现在函数声明中返回值位置。这种情况下,auto并不是告诉编译器去推断返回类型,而是指引编译器去函数的末端寻找返回值类型。在下面这个例子中,函数的返回值类型就是operator+操作符作用在T1、T2类型变量上的返回值类型。

template <typename T1, typename T2>
auto compose(T1 t1, T2 t2) -> decltype(t1 + t2)
{
   return t1+t2;
}
auto v = compose(2, 3.14); 
// v's type is double

2、 auto不能用作函数的形参,如果传递匿名函数,需要使用std::function

#include <functional>

void invoke(std::function<int(int&, int&)> func) {
	int a = 10, b = 22;
	int sum = func(a, b);
}

void main() {
	std::function<int(int&, int&)> swap_func = [](int& a, int& b) -> int {
		a ^= b;
		b ^= a;
		a ^= b;
		return (a+b);
	};

	invoke(swap_func);
}

六、C++临时对象

实例

#include <stdio.h>

class Test {
public:
	Test(int a) : data(a) {}
	Test(const Test& t);
	~Test();
	const Test& operator=(const Test& t);
private:
	int data;
};

Test::Test(const Test& t) {
	data = t.data;
}

Test::~Test(){
	printf("%s\n", __FUNCTION__);
}

const Test& Test::operator=(const Test& t) {
	data = t.data;
	return (*this);
}

Test test() {
	Test tt(12);
	return tt;
}

int main() {

#if 0
	Test t(22);
	t = test();
#else
	Test t = test();
#endif

	return 0;
}

参考文档

七、多线程编程之<future>

参考文档

八、可变参数个数的模板

在C++11 之前, 不论是模板类或是模板函数,都只能按其被声明时所指定的样子,接受一组固定数目的模板实参;
C++11 加入新的表示法,允许任意个数、任意类别的模板实参,不必在定义时将实参的个数固定。

template<typename... Values> class tuple;

模板类tuple 的对象,能接受不限个数的typename 作为它的模板形参:

class tuple<int, std::vector<int>, std::map<std::string, std::vector<int>>> someInstanceName

实参的个数也可以是 0,所以class tuple<> someInstanceName 这样的定义也是可以的。

若不希望产生实参个数为0 的变长参数模板,则可以采用以下的定义:

template<typename First, typename... Rest> class tuple;

变长参数的数量可以藉以下的语法得知:

template<typename ...Args> struct SomeStruct
{
	static const int size = sizeof...(Args);
}

参考实例:

#include <iostream>

void printf(const char *s)
{
	while (*s)
	{
		if (*s == '%' && *(++s) != '%')
			throw std::runtime_error("invalid format string: missing arguments");
		std::cout << *s++;
	}
}

template<typename T, typename... Args>
void printf(const char* s, T value, Args... args)
{
	while (*s)
	{
		if (*s == '%' && *(++s) != '%')
		{
			std::cout << value;
			printf(*s ? ++s : s, args...); // 即便当*s == '\0' 也会产生调用,以检测更多的类型参数。
			return;
		}
		std::cout << *s++;
	}
	throw std::logic_error("extra arguments provided to printf");
}

详细介绍参考:C++11标准中文版文档6.1 变长参数模板

参考网址C++11中可变参数个数的模板(variadic template)

九、lambda匿名函数

#include <functional>

class Test {
public:
	std::function<int()> set(int a);
private:
	int data;
};

std::function<int()> Test::set(int a) {
	data = a;
	auto fun = [this]() -> int {
		return this->data++;
	};
	return fun;
}

void main() {
	Test t1;
	auto fun = t1.set(1032);
	int a = fun();
}
#include <functional>

class Test {
public:
	std::function<int()>* set(int a);
private:
	int data;
};

std::function<int()>* Test::set(int a) {
	data = a;
	auto fun = new std::function<int()>([this]() -> int {
		return this->data++;
	});
	return fun;
}

void main() {
	Test t1;
	auto fun = t1.set(1032);
	int a = (*fun)();
	delete fun;
}
#include <functional>

class Test {
public:
	void set(int a);
	inline int get() { return data; }
	std::function<int(int)>* set(std::function<int(int)> func);
private:
	int data;
};

void Test::set(int a) {
	data = a;
}

std::function<int(int)>* Test::set(std::function<int(int)> func) {
	auto fun = new std::function<int(int)>(func);
	return fun;
}

void main() {
	Test t1;
	auto func = [&](int a) -> int {
		t1.set(a);
		return t1.get();
	};
	auto fun = t1.set(func);
	int a = (*fun)(1023);
	delete fun;
	int b = func(2048);
}
#include <functional>

class Test {
public:
	Test(int a) : data(a) {}
	std::function<int(int)> set(int a);
	inline void increase(int a) { data += a; }
private:
	int data;
};

std::function<int(int)> Test::set(int a) {
	data = a;
	auto fun = [this](int a) -> int {
		this->data = a;
		return this->data;
	};
	return fun;
}

void main() {
	Test* pTest = new Test(10);
	auto fun = pTest->set(1032);
	delete pTest;
	pTest = nullptr;
	int a = fun(20);
	pTest->increase(20);	//error
}

lambda匿名函数一般格式: capturelistcapture-list ( params ) -> ret { body }

capture-list can be passed as follows (see below for the detailed description):
[a,&b] where a is captured by value and b is captured by reference.
[this] captures the this pointer by value
[&] captures all automatic variables odr-used in the body of the lambda by reference
[=] captures all automatic variables odr-used in the body of the lambda by value
[] captures nothing

capture使用心得:

参考网址C++官网 Lambda functions (since C++11)

capture: this

#include <functional>

class A {
public:
	virtual void test() = 0;

protected:
	//A() { std::cout << "A::A" << std::endl; }
	virtual ~A() { std::cout << "A::~A" << std::endl; }
	void testA() { std::cout << "A::testA" << std::endl; }
};

class C {
public:
	C() { std::cout << "C::C" << std::endl; }
	C(const C& other) { std::cout << "C::C copy function" << std::endl; }
	~C() { std::cout << "C::~C" << std::endl; }
	void testC() const { std::cout << "C::testC" << std::endl; }
};

class B : public A {
public:
	B() { std::cout << "B::B" << std::endl; }
	~B() { std::cout << "B::~B" << std::endl; }
	virtual void test() { std::cout << "B::test" << std::endl; }
	void testB() { std::cout << "B::testB" << std::endl; }
	void invoke(std::function<void ()>& functor) {
		C c1;
		functor = [this, c1]() { // const C c1
			this->testA();
			this->testB();
			c1.testC();
		};
	}
};

int main() {
	{
		B b1;
		std::function<void ()> functor;
		{
			std::function<void ()> callback;
			b1.invoke(callback);
			functor = callback;
			callback();
		}
		functor();
	}

	return 0;
}

打印信息:

B::B
C::C
C::C copy function
C::C copy function
C::~C
C::~C
C::C copy function
A::testA
B::testB
C::testC
C::~C
A::testA
B::testB
C::testC
C::~C
B::~B
A::~A

十、 lambda应用之ScopeGuard

scopeguard.h

#ifndef scopeguard_h__
#define scopeguard_h__

#include <utility>

namespace sg
{
    template <class Fun>
    class ScopeGuard {
        Fun f_;
        bool active_;
    public:
        ScopeGuard(Fun f)
            : f_(std::move(f))
            , active_(true) {
        }
        ~ScopeGuard() { if (active_) f_(); }
        void dismiss() { active_ = false; }
        ScopeGuard(ScopeGuard&& rhs)
            : f_(std::move(rhs.f_))
            , active_(rhs.active_) {
                rhs.dismiss();
        }
    };

    namespace detail {
        class ScopeGuardOnExit {};
        template <typename Fun>
        ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun&& fn) {
            return ScopeGuard<Fun>(std::forward<Fun>(fn));
        }
    }
}

#define SCOPE_EXIT \
    auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
	= sg::detail::ScopeGuardOnExit() + [&]()

#define CONCATENATE_IMPL(s1, s2) s1##s2
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
#ifdef __COUNTER__
#define ANONYMOUS_VARIABLE(str) \
    CONCATENATE(str, __COUNTER__)
#else
#define ANONYMOUS_VARIABLE(str) \
    CONCATENATE(str, __LINE__)
#endif

#endif // scopeguard_h__

main.cpp

#include <stdio.h>
#include "scopeguard.h"

int test() {
	SCOPE_EXIT{
		printf("end of test()\n");
	};
	return 0;
}

void main() {

	test();

	{
		SCOPE_EXIT{
			printf("end of main()\n");
		};
	}
}

参考文档如何退出函数时再做一些固定的事情(比如释放内存)--scopeguard

=====================================================================

参考文档

=====================================================================

测试用例

#include <atomic>
#include <memory>
#include <thread>
#include <functional>
#include <map>
#include <list>
#include <vector>
#include <algorithm>
#include <iostream>

template <typename T1, typename T2>
auto compose(T1 t1, T2 t2) -> decltype(t1 + t2)
{
	return t1+t2;
}

namespace lsclone {

	class Mem {
	public:
		~Mem();
		Mem() : m_str(nullptr), m_len(0) {}
		Mem(const char* str, int len);
		Mem(const Mem& obj);
		Mem(Mem&& obj);
		Mem& operator=(Mem&& obj);
		void set(const char* str, int len);
		void show();

	private:
		int m_len;
		char* m_str;
	};

	Mem::~Mem() {
		if (m_str != nullptr) {
			delete[] m_str;
		}
	}

	Mem::Mem(const char* str, int len) {
		m_str = new char[len + 1];
		memcpy(m_str, str, len);
		m_str[len] = '\0';
		m_len = len;
	}

	Mem::Mem(const Mem& obj) {
		m_str = new char[obj.m_len + 1];
		memcpy(m_str, obj.m_str, obj.m_len);
		m_str[obj.m_len] = '\0';
		m_len = obj.m_len;
	}

	// move construction
	Mem::Mem(Mem&& obj) {
		m_str = obj.m_str;
		m_len = obj.m_len;
		obj.m_str = nullptr;
		obj.m_len = 0;
	}

	// move assignment operator
	Mem& Mem::operator=(Mem&& obj) {
		std::swap(m_str, obj.m_str);
		std::swap(m_len, obj.m_len);
		return (*this);
	}

	void Mem::set(const char* str, int len) {
		if (m_str != nullptr) {
			delete m_str;
			m_str = nullptr;
		}
		m_str = new char[len + 1];
		memcpy(m_str, str, len);
		m_str[len] = '\0';
		m_len = len;
	}

	void Mem::show() {
		if (m_str != nullptr) {
			printf("%s\n", m_str);
		}
	}

	class Mem2 {
	public:
		Mem2(const char* str, int len) : mObj(str, len) {}
	private:
		Mem mObj;
	};
}

typedef struct _Info {
	int data;
}Info;

void func(std::function<int(int&, int&)> swap_func) {
	int a = 10, b = 22;
	int sum = swap_func(a, b);
}

class A {
public:
	virtual void test() = 0; //{ std::cout << "A::test" << std::endl; }
	void testA() { std::cout << "A::testA" << std::endl; }

protected:
	//A() { std::cout << "A::A" << std::endl; }
	virtual ~A() { std::cout << "A::~A" << std::endl; }
};

class B : public A {
public:
	B() { std::cout << "B::B" << std::endl; }
	~B() { std::cout << "B::~B" << std::endl; }
	virtual void test() { std::cout << "B::test" << std::endl; }
	void testB() { std::cout << "B::testB" << std::endl; }
};

int main() {

	std::shared_ptr<A> spa(new B);
	std::shared_ptr<B> spb = std::dynamic_pointer_cast<B>(spa);
	if (spb) {
		std::cout << spa.use_count() << std::endl; // 2
		std::cout << spb.use_count() << std::endl; // 2
	}

	int arr[] = {1,2,3};
	std::for_each(std::begin(arr), std::end(arr), [](int num) {std::cout << num << std::endl;});
 
	auto is_odd = [](int n) {return n%2==1;};
	auto pos = std::find_if(std::begin(arr), std::end(arr), is_odd);
	if(pos != std::end(arr)) {
		std::cout << *pos << std::endl;
		*pos += 100;
	}

	auto is_odd2 = is_odd;
	bool oddret = is_odd2(10);


	auto swap_func = [](int& a, int& b) -> int {
		a ^= b;
		b ^= a;
		a ^= b;
		return (a+b);
	};

	func(swap_func);

	lsclone::Mem2 mm1("hello", strlen("hello"));

	auto v = compose<double, double>(2, 3.14); 

	int a[2] = {15, 20};
	int b = 10;
	auto sum = [&b](double t1, double t2) -> double { b = 22; return (t1+t2);};

	printf("%.2f    %d\n", sum(1.2, 0.98), b); // printf b 10 !!!
	printf("b: %d\n", b);


	std::function<int(int)> lfib = [&lfib](int n) {return n < 2 ? 1 : lfib(n-1);};

	auto res = lfib(100);
	printf("%d\n", res);


	lsclone::Mem m1("string", strlen("string"));
	lsclone::Mem m2(m1);
	lsclone::Mem m3(std::move(m1));
	lsclone::Mem m4(lsclone::Mem("123", 3));

	std::list<Info> nlist;
	Info f1, f2;
	f1.data = 10;
	f2.data = 20;
	nlist.push_back(f1);
	nlist.push_back(f2);

	std::list<Info>::iterator listIt = nlist.begin();
	for (; listIt != nlist.end(); listIt++) {
		(*listIt).data += 5;
	}

	std::list<int> ilist;
	ilist.push_back(12);
	ilist.push_back(22);

	std::list<int>::iterator iIt = ilist.begin();
	for (; iIt != ilist.end(); iIt++) {
		*iIt = 6;
	}

	std::vector<std::string> strVec;
	strVec.push_back("hello");
	strVec.push_back("world");
	strVec.push_back("end");

	std::list<lsclone::Mem> mlist;
#if 0
	lsclone::Mem eleMem;
	for (int i = 0; i<3; i++) {
		eleMem.set(strVec[i].c_str(), strVec[i].size());
		mlist.push_back(std::move(eleMem));
	}
#else
	mlist.push_back(std::move(lsclone::Mem("hello", strlen("hello"))));
	mlist.push_back(std::move(lsclone::Mem("world", strlen("world"))));
#endif

	for (auto it = mlist.begin(); it != mlist.end(); it++ ) {
		it->show();
	}

	for (auto& ele: mlist) {
		ele.show();
	}


	std::map<int, lsclone::Mem> mp;
	mp[0] = std::move(lsclone::Mem("hello", strlen("hello")));
	mp[1] = std::move(lsclone::Mem("world", strlen("world")));

	auto it = mp.find(1);
	if (it != mp.end()) {
		it->second.show();
		it->second.set("end", strlen("end"));
	}


	std::list<int> list1;
	list1.push_back(10);
	list1.push_back(20);
	list1.push_back(30);

	std::for_each(list1.begin(), list1.end(), [](int item){
		printf("list item: %d\n", item); });

	return 0;
}

参考网址: c++官网for_each函数