文章目录
- 2.C++默认实参
- 21.模板模板形参
- 22.C++11形参包
- 24.std::nothrow
- 25.std::call_once与pthread_once
2.C++默认实参
21.模板模板形参
模板参数:是一个模板类型
#include <string>
#include <iostream>
template<typename T>
struct X{};
template<typename Z, template<typename T> typename C>
struct Y{
C<Z> c;
};
template<class T>
struct X2{
T t;
};
template<template<typename T, typename T2, typename T3> typename S>
struct Str{
S<char, std::char_traits<char>, std::allocator<char>> str;
};
int main()
{
Y<int, X2> y{};
y.c.t=100;
std::cout<<y.c.t<<'\n';
Str<std::basic_string> s;
s.str="abc";
std::cout<<s.str<<'\n';
}
22.C++11形参包
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
template<size_t...args>
struct X{
void f(){
for(const auto& i: {args...})
{
std::cout<<i<<' ';
std::cout<<'\n';
}
}
};
template<typename...Args>
void f(Args...args)
{
((std::cout<<args<<' '),...);
}
template<typename T1, typename T2>
struct T{};
template<template<typename T1, typename T2>typename...Args>
struct Y{};
void print(){}
template<typename T, typename ...Args>
void print(T t, Args...args)
{
std::cout<<t<<' ';
print(args...);
}
template<size_t...Args>
void t()
{
int array[sizeof...(Args)]{Args...};
for(auto const& i: array)
{
std::cout<<i<<' ';
}
endl(std::cout);
}
int main()
{
X<1,2,3> x;
x.f();
f(4,5,6,"wangji");
Y<std::basic_string,T,T>y;
endl(std::cout);
print('a','b');
t<1,2>();
}
24.std::nothrow
当使用new申请一块内存失败时,抛出异常std::bad_alloc是C++标准中规定的标准行为,所以使用try { p = new int[size];} catch(std::bad_alloc) { … } 的处理方式。
std::nothrow与标准new的区别是,new在分配内存失败时会抛出异常,而"new(std::nothrow)"在分配内存失败时会返回一个空指针。
new operator分配内存失败后,缺省的行为不是返回NULL,而是抛出异常std::bad_alloc。所以判断返回值是否为NULL没有任何意义
#include <iostream>
#include <new>
int test_nothrow1()
{
std::cout << "Attempting to allocate 1 MiB...";
char* p = new (std::nothrow) char[1048576];
if (p == 0)
std::cout << "Failed!\n";
else {
std::cout << "Succeeded!\n";
delete[] p;
}
return 0;
}
int test_nothrow2()
{
try {
while (true) {
new int[100000000ul];
}
}
catch (const std::bad_alloc& e) {
std::cout << e.what() << '\n';
}
while (true) {
int* p = new(std::nothrow) int[100000000ul];
if (p == nullptr) {
std::cout << "Allocation returned nullptr\n";
break;
}
}
return 0;
}
25.std::call_once与pthread_once
pthread_once可以实现多线程的单例,且可以在函数中注册好单例对象的退出函数;
- ref:muduo:Singleton.h
- has_no_destroy
#ifndef MUDUO_BASE_SINGLETON_H
#define MUDUO_BASE_SINGLETON_H
#include <assert.h>
#include <pthread.h>
#include <stdlib.h>
#include "muduo/base/noncopyable.h"
namespace muduo {
namespace detail {
template <typename T>
struct has_no_destroy {
template <typename C>
static char test(decltype(&C::no_destroy));
template <typename C>
static int32_t test(...);
const static bool value = sizeof(test<T>(0)) == 1;
};
}
template <typename T>
class Singleton : noncopyable {
public:
Singleton() = delete;
~Singleton() = delete;
static T& instance() {
pthread_once(&ponce_, &Singleton::init);
assert(value_ != NULL);
return *value_;
}
private:
static void init() {
value_ = new T();
if (!detail::has_no_destroy<T>::value) {
::atexit(destroy);
}
}
static void destroy() {
typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
T_must_be_complete_type dummy;
(void)dummy;
delete value_;
value_ = NULL;
}
private:
static pthread_once_t ponce_;
static T* value_;
};
template <typename T>
pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;
template <typename T>
T* Singleton<T>::value_ = NULL;
}
#endif
std::call_once功能类似于pthread_once,但是单例对象的析构还得使用atexit
- std::call_once函数第一个参数是std::once_flag的一个对象,第二个参数可以是函数、成员函数、函数对象、lambda函数。
template< class Function, class... Args >
void call_once ( std::once_flag& flag, Function&& f, Args&& args... );
参数解析:
flag - an object, for which exactly one function gets executed
f - 需要被调用的函数
args... - 传递给函数f的参数(可以多个)
返回值为 (none)
抛出异常
std::system_error if any condition prevents calls to call_once from executing as specified any exception thrown by f
#include <iostream>
#include <thread>
#include <mutex>
std::once_flag flag1;
void simple_do_once()
{
std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; });
}
int main()
{
std::thread st1(simple_do_once);
std::thread st2(simple_do_once);
std::thread st3(simple_do_once);
std::thread st4(simple_do_once);
st1.join();
st2.join();
st3.join();
st4.join();
}
参考:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)