C++11 function、bind、可变参数模板

2023-10-27

在设计回调函数的时候,无可避免地会接触到可回调对象。在C++11中,提供了std::function和 std::bind两个方法来对可回调对象进行统一和封装。 C++语言中有几种可调用对象:函数、函数指针、lambda表达式、bind创建的对象以及重载了函数调用 运算符的类。 和其他对象一样,可调用对象也有类型。例如,每个lambda有它自己唯一的(未命名)类类型;函数及函数指针的类型则由其返回值类型和实参类型决定。

function的用法

1. 保存普通函数

//保存普通函数
void func1(int a)
{
cout << a << endl;
}
//1. 保存普通函数
std::function<void(int a)> func;
func = func1;
func(2); //2

2. 保存lambda表达式

std::function<void()> func_1 = [](){cout << "hello world" << endl;};
func_1(); //hello world

3. 保存成员函数

//保存成员函数
class A{
public:
A(string name) : name_(name){}
void func3(int i) const {cout <<name_ << ", " << i << endl;}
private:
string name_;
};
//3 保存成员函数
std::function<void(const A&,int)> func3_ = &A::func3;
A a("darren");
func3_(a, 1);
#include <iostream>
#include <functional> // 添加头文件 functional
using namespace std;
// function 类似c的函数指针
//保存普通函数
void func1(int a)
{
    cout << a << endl;
}
//保存成员函数
class A {
public:
    A(string name) : name_(name) {}
    void func3(int i) const { cout << name_ << ", " << i << endl; }
    // void func3(string str) const {cout <<name_ << ", " << str << endl;}

    //    std::bind((void(A::*)(int, int))&A::fun_4
    void func4(int k, int m)
    {
        cout << "func4 print: k=" << k << ",m=" << m << endl;
    }
    //    std::bind((void(A::*)(string))&A::fun_4
    void func4(string str) {
        cout << "func4 print: str=" << str << endl;
    }
private:
    string name_;
};
int main()
{
    cout << "main1 -----------------" << endl;
    //1. 保存普通函数
    std::function<void(int a)> func1_;
    func1_ = func1;
    func1_(2);   //2
    cout << "\n\nmain2 -----------------" << endl;
    //2. 保存lambda表达式
    std::function<void()> func2_ = []() {cout << "hello lambda" << endl; };
    func2_();  //hello world
    cout << "\n\nmain3 -----------------" << endl;
    //3 保存成员函数
    std::function<void(const A&, int)> func3_ = &A::func3;
    A a("darren");
    func3_(a, 1);
    //4.重载函数
    std::function<void(int, int)> func4_1 = std::bind((void(A::*)(int, int)) & A::func4, a, std::placeholders::_1, std::placeholders::_2);
    func4_1(1, 2);
    auto f_str = std::bind((void(A::*)(string)) & A::func4, a, std::placeholders::_1);
    f_str("darren");
    std::function<void(string)> f_str2 = std::bind((void(A::*)(string)) & A::func4, &a, std::placeholders::_1);
    return 0;
}

bind用法

可将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。 调用bind的一般形式:auto newCallable = bind(callable, arg_list);

其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。即,当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数。

arg_list中的参数可能包含形如n的名字,其中n是一个整数,这些参数是“占位符”,表示newCallable的参 数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对象中参数的位置:1为 newCallable的第一个参数,_2为第二个参数,以此类推。

#include <iostream>
#include <functional>
using namespace std;
class A
{
public:
    // 重载fun_3,主要bind的时候需要
//    std::bind((void(A::*)(int, int))&A::fun_3
    void fun_3(int k, int m)
    {
        cout << "fun_3 a = " << a << endl;
        cout << "print: k=" << k << ",m=" << m << endl;
    }
    //    std::bind((void(A::*)(string))&A::fun_3
    void fun_3(string str) {
        cout << "print: str=" << str << endl;
    }
    int a;
};
void fun_1(int x, int y, int z)
{
    cout << "fun_1 print: x=" << x << ",y=" << y << ",z=" << z << endl;
}
void fun_2(int& a, int& b)
{
    a++;
    b++;
    cout << "print: a=" << a << ",b=" << b << endl;
}
void func2_1(int a, int b)
{
    cout << "func2_1 a + b = " << a + b << endl;
}
int func2_1(string a, string b)
{
    cout << "func2_1 a + b = " << a << b << endl;
    return 0;
}
int main()
{
    auto f2_1_1 = std::bind((void(*)(int, int))func2_1, 1, 2); //表示绑定函数 fun 的第一,二,三个参数值为: 1 2 3
    f2_1_1(); //print: x=1,y=2,z=3
#if 1
    //f1的类型为 function<void(int, int, int)>
    cout << "\n\nstd::bind(fun_1, 1, 2, 3) -----------------\n";
    auto f1 = std::bind(fun_1, 1, 2, 3); //表示绑定函数 fun 的第一,二,三个参数值为: 1 2 3    运行的时候不需要再传递参数
    f1(); //print: x=1,y=2,z=3
    cout << "\n\nstd::bind(fun_1, 10, 20, 30) -----------------\n";
    auto f11 = std::bind(fun_1, 10, 20, 30); //表示绑定函数 fun 的第一,二,三个参数值为: 1 2 3
    f11();
    cout << "\n\nstd::bind(fun_1, placeholders::_1,placeholders::_2, 3) -----------------\n";
    auto f2 = std::bind(fun_1, placeholders::_1, placeholders::_2, 3);       // 锁定第三个参数  ,   绑定参数是从1开始的,placeholders::_1(占位符),和数组索引有所不同
    //表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f2 的第一,二个参数指定
    f2(1, 2);//print: x=1,y=2,z=3
    f2(10, 21, 30); // 传入30也没有用
#endif
//    cout << "\n\nstd::bind(fun_1,placeholders::_2,placeholders::_1,3) -----------------\n";
//    auto f3 = std::bind(fun_1,placeholders::_2,placeholders::_1,3);
//    //表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f3 的第二,一个参数指定
//    //注意: f2  和  f3 的区别。
//    f3(1,2);//print: x=2,y=1,z=3
//    cout << "\n\nstd::bind(fun_2, placeholders::_1, n) -----------------\n";
//    int m = 2;
//    int n = 3;
//    auto f4 = std::bind(fun_2, placeholders::_1, n); //表示绑定fun_2的第一个参数为n, fun_2的第二个参数由调用f4的第一个参数(_1)指定。
//    f4(m); //print: m=3,n=4
//    cout<<"m="<<m<<endl;//m=3  说明:bind对于不事先绑定的参数,通过std::placeholders传递的参数是通过引用传递的,如m
//    cout<<"n="<<n<<endl;//n=3  说明:bind对于预先绑定的函数参数是通过值传递的,如n
//#if 1
    cout << "\n\nstd::bind(&A::fun_3, &a,placeholders::_1,placeholders::_2) -----------------\n";
    A a;
    a.a = 10;
    //f5的类型为 function<void(int, int)>
    auto f5 = std::bind((void(A::*)(int, int)) & A::fun_3, &a, 40, 50); //使用auto关键字
    f5(10, 20);//调用a.fun_3(10,20),print: k=10,m=20
    cout << "\n\nstd::bind(&A::fun_3, &a2,placeholders::_1,placeholders::_2) -----------------\n";
    A a2;
    a2.a = 20;
    //f5的类型为 function<void(int, int)>
    auto f6 = std::bind((void(A::*)(int, int)) & A::fun_3, &a2, placeholders::_1, placeholders::_2); //使用auto关键字
    f6(10, 20);
//    cout << "\n\nstd::bind(&A::fun_3, a,std::placeholders::_1,std::placeholders::_2) -----------------\n";
//    std::function<void(int,int)> fc = std::bind((void(A::*)(int, int))&A::fun_3, a,std::placeholders::_1,std::placeholders::_2);
//    fc(10,20);   //调用a.fun_3(10,20) print: k=10,m=20
//    fc = std::bind((void(A::*)(int, int))&A::fun_3, a2,std::placeholders::_1,std::placeholders::_2);
    cout << "\n\nstd::bind(&A::fun_3, a,std::placeholders::_1,std::placeholders::_2) ----\n";
    auto f_str = std::bind((void(A::*)(string)) & A::fun_3, a, std::placeholders::_1);
    f_str("darren");
    //#endif
    return 0;
}

可变模板参数

C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进 行了高度泛化,它能表示0到任意个数、任意类型的参数

可变模版参数的展开

可变参数模板语法

template<class... T> 

void f(T... args);

上面的可变模版参数的定义当中,省略号的作用有两个:

1. 声明一个参数包T... args,这个参数包中可以包含0到任意个模板参数;

2. 在模板定义的右边,可以将参数包展开成一个一个独立的参数。

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”, 它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展 开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特点,也是最大的难 点,即如何展开可变模版参数。 可变模版参数和普通的模版参数语义是一致的,所以可以应用于函数和类,即可变模版参数函数和可变 模版参数类,然而,模版函数不支持偏特化,所以可变模版参数函数和可变模版参数类展开可变模版参 数的方法还不尽相同,下面我们来分别看看他们展开可变模版参数的方法。

可变模版参数函数

#include <iostream>
using namespace std;
template <class... T>
void f(T... args)
{
cout << sizeof...(args) << endl; //打印变参的个数
}
int main()
{
f(); //0
f(1, 2); //2
f(1, 2.5, ""); //3
return 0;
}

上面的例子中,f()没有传入参数,所以参数包为空,输出的size为0,后面两次调用分别传入两个和三个 参数,故输出的size分别为2和3。由于可变模版参数的类型和个数是不固定的,所以我们可以传任意类 型和个数的参数给函数f。这个例子只是简单的将可变模版参数的个数打印出来,如果我们需要将参数包 中的每个参数打印出来的话就需要通过一些方法了。 展开可变模版参数函数的方法一般有两种:

1. 通过递归函数来展开参数包

2. 是通过逗号表达式来展开参数包。

下面来看看如何用这两种方法来展开参数包。

递归函数方式展开参数包

通过递归函数展开参数包,需要提供一个参数包展开的函数和一个递归终止函数,递归终止函数正是用来终止递归的

#include <iostream>
using namespace std;
//递归终止函数
void print()
{
    cout << "empty" << endl;
}
//展开函数
template <class T, class ...Args>
void print(T head, Args... rest)
{
    cout << "parameter " << head << endl;
    print(rest...);
}
int main(void)
{
    print(1,2,3,4);
    return 0;
}

上例会输出每一个参数,直到为空时输出empty。展开参数包的函数有两个,一个是递归函数,另外一 个是递归终止函数,参数包Args...在展开的过程中递归调用自己,每调用一次参数包中的参数就会少一 个,直到所有的参数都展开为止,当没有参数时,则调用非模板函数print终止递归过程。

上面的递归终止函数还可以写成这样:

template <class T>
void print(T t)
{
    cout << t << endl;
}

逗号表达式展开参数包

递归函数展开参数包是一种标准做法,也比较好理解,但也有一个缺点,就是必须要一个重载的递归终止 函数,即必须要有一个同名的终止函数来终止递归,这样可能会感觉稍有不便。有没有一种更简单的方 式呢?其实还有一种方法可以不通过递归方式来展开参数包,这种方式需要借助逗号表达式和初始化列 表。比如前面print的例子可以改成这样:

#include <iostream>
using namespace std;
template <class T>
void printarg(T t)
{
    cout << t << endl;
}
template <class ...Args>
void expand(Args... args)
{
    int arr[] = {(printarg(args), 0)...};
}
int main()
{
    expand(1,2,3,4);
    return 0;
}

这个例子将分别打印出1,2,3,4四个数字。这种展开参数包的方式,不需要通过递归终止函数,是直接在 expand函数体中展开的, printarg不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。expand函数中的逗号表达式:(printarg(args), 0),先执行printarg(args),再得到逗号表达式的结果0。 同时还用到了C++11的另外一个特性——初始化列表,通过初始化列表来初始化一个变长数组, {(printarg(args), 0)...}将会展开成((printarg(arg1),0), (printarg(arg2),0), (printarg(arg3),0), etc... ),最 终会创建一个元素值都为0的数组int arr[sizeof...(Args)]。由于是逗号表达式,在创建数组的过程中会先 执行逗号表达式前面的部分printarg(args)打印出参数,也就是说在构造int数组的过程中就将参数包展开 了,这个数组的目的纯粹是为了在数组构造的过程展开参数包。我们可以把上面的例子再进一步改进一 下,将函数作为参数,就可以支持lambda表达式了,从而可以少写一个递归终止函数了,具体代码如下:

#include <iostream>
using namespace std;
template<class F, class... Args>void expand(const F& f, Args&&...args)
{
    //这里用到了完美转发
    initializer_list<int>{(f(std::forward< Args>(args)),0)...};
}
int main()
{
    expand([](int i){cout<<i<<endl;}, 1,2,3);
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11 function、bind、可变参数模板 的相关文章

  • 高级 Win32 图像文件 I/O?

    我想在 Windows C 应用程序中将图像文件读入内存 什么是一个相当简单的解决方案 也许类似于 IOS 提供的UIImage 我希望支持合理数量的文件格式 我需要为图像处理的位图提供一些低级访问权限 我在互联网上阅读了很多内容 看起来
  • 如何向 UWP 项目添加 .NET dll 引用?

    我有几个适用于 NETv4 x 的 NET dll 项目 我将版本更改为 4 6 1 并重新构建 没有出现问题 当我尝试从 UWP 项目向它们添加引用时 出现错误 项目的目标是 NETCore 而文件引用的目标是 NET框架 这不是受支持的
  • 如何从当前 .NET 表单/应用程序发送密钥 F12

    我非常确定以下按钮激活的表单代码应该在我的 C 应用程序中引发 Control F12 SendKeys F12 但它似乎并没有继续进入 Windows shell 并激活另一个正在侦听它的程序 我的键盘可以用 看起来发送键在某处被拦截 并
  • 将 2D 数组映射到 1D 数组

    我想用一维数组来表示一个二维数组 函数将传递两个索引 x y 和要存储的值 这两个索引代表一维数组的单个元素 并相应地设置它 我知道一维数组需要具有 arrayWidth arrayHeight 的大小 但我不知道如何设置每个元素 例如 如
  • Linq Where 本地计数器关闭在 VS watch 中的结果不同

    我尝试删除前 3 个元素array与 LinQWhere扩展功能 这是一个例子 var array new 1 2 3 4 5 6 7 8 9 var count 3 var deletedTest1 0 var test1 array W
  • 对数字进行向上和向下舍入 C++

    我试图让我的程序分别向上和向下舍入数字 例如 如果数字是3 6 我的程序应该四舍五入最接近的数字 4 如果该数字是3 4 它将向下舍入为 3 我尝试使用ceil库获取 3 个项目的平均值 results ceil marks1 marks2
  • Qt中正确的线程方式

    我的图像加载非常耗时 图像很大 并且在加载时也完成了一些操作 我不想阻止应用程序 GUI 我的想法是在另一个线程中加载图像 发出图像已加载的信号 然后用该图像重绘视图 我的做法 void Window loadImage ImageLoad
  • 如何避免选择项目时 winforms 树视图图标发生变化

    我正在一个小型 C Winforms 应用程序中尝试树视图 我已经以编程方式将 ImageList 分配给树视图 并且所有节点都很好地显示了它们的图标 but当我单击一个节点时 它的图标会发生变化 变为 ImageList 中的第一个图像
  • C中有const吗?

    这个问题可能很幼稚 但是 有没有constC 中的关键字 从哪个版本开始 之间有任何语义和 或句法差异吗const在 C 和 C 中 C 和 C 之间在语法上没有差异const关键字 除了一个相当晦涩的关键字 在 C 中 自 C99 起 您
  • C#:如何使用 SHOpenFolderAndSelectItems [重复]

    这个问题在这里已经有答案了 有人可以举例说明如何使用 shell 函数吗SH打开文件夹并选择项目 http msdn microsoft com en us library bb762232 VS 85 aspx来自 C 我不太明白如何使用
  • 使用 Linq 进行异步Where过滤

    我有一个List通过填充的元素async调用 WebService 没问题 我需要过滤该列表以便在应用程序视图上显示某些内容 我试过这个 List
  • 使用 AutoMapper 进行 LINQ GroupBy 聚合

    试图让查询工作 但老实说不确定如何 或者是否可能 进行它 因为我尝试过的一切都不起作用 共查询6个表 Person PersonVote PersonCategory Category City FirstAdminDivision Per
  • 为什么 C 函数不能返回数组类型?

    我是 C 语言新手 想知道 为什么 C 函数不能返回数组类型 我知道数组名是数组第一个值的地址 而数组是 C 中的二等公民 您自己已经回答了这个问题 数组是二等公民 C 按值返回 数组不能按值传递 因此不能返回它们 至于为什么数组不能按值传
  • 如何使用 Clang 查找内存泄漏

    我在我的机器 ubuntu 中安装了 Clang 以便发现我的 C 代码中的内存泄漏 我编写了一个示例代码来检查它的工作情况 如下所示 File hello c for leak detection include
  • SSBO 是更大的 UBO?

    我目前正在 OpenGL 4 3 中使用 UBO 进行渲染 以将所有常量数据存储在 GPU 上 诸如材料描述 矩阵等内容 它可以工作 但是 UBO 的小尺寸 我的实现为 64kB 迫使我多次切换缓冲区 减慢渲染速度 我正在寻找类似的方法来存
  • 删除对象时指针自动指向空

    假设我有一个对象和其他几个不同类类型的对象中的 10 个指向它的指针 如果对象被删除 这些指针必须设置为空 通常我会将对象的类与具有指向它的指针的类互连 以便它可以通知它们它正在被删除 并且它们可以将它们的指针设置为空 但这也有一个负担 即
  • 在 unix 中编译 dhrystone 时出错

    我是使用基准测试和 makefile 的新手 我已经从下面的链接下载了 Dhrystone 基准测试 我正在尝试编译它 但我遇到了奇怪的错误 我尝试解决它 但没有成功 有人可以帮助我运行 dhrystone 基准测试吗 以下是我尝试编译的两
  • 局部静态变量初始化是线程安全的[重复]

    这个问题在这里已经有答案了 假设我有一个包含三个静态函数的类 如下所示 include
  • 如何仅更改 DateTime 的日期部分,同时保留时间部分?

    我在代码中使用了很多 DateTime 我想将这些日期时间更改为我的特定日期并保留 时间 1 2012 02 02 06 00 00 gt 2015 12 12 06 00 00 2 2013 02 02 12 00 00 gt 2015
  • C++0x 中的新 unicode 字符

    我正在构建一个 API 它允许我获取各种编码的字符串 包括 utf8 utf16 utf32 和 wchar t 根据操作系统 可能是 utf32 或 utf16 新的 C 标准引入了新类型char16 t and char32 t没有这么

随机推荐

  • AsyncTask的实用-中断请求实现

    平时的app网络操作一般有几种方式 new Thread handler new AsyncTask 我常用的方式是new AsyncTask 可能比较方便吧 弊端 就是一旦请求 没有焦点 只能等待黑圈转完 new Thread 好处是好控
  • 【实践2】Python openpyxl获取Excel所有表名,删除Excel内指定工作表(判断是否存在某个sheet,存在即删除)

    简单介绍 定时爬虫任务会有每天使用pandas将数据写入Excel表中的动作 但每天写入的行数会有不同 例如第一天写入5000行而第二天只写入3000行 会导致该表中前3000行是最新数据 后2000是前一天的数据 因此最好的方法是在将数据
  • Magento关于添加Robots.txt文件

    在 Magento和其他电子商务平台的SEO话题中 有一个很常见的问题 怎样写robots txt文件 里面到底应该包含哪些内容 为了很好滴回答这个问题 我将根据我所有的知识和经验尝试找出一个最佳的robots txt文件写法 下面部分ro
  • 时间SQL查询大全

    查询15天之前得数据 modifydate 是数据库得时间字段格式yyyy MM dd hh mm ss SELECT FROM 表名 where DATE SUB CURDATE INTERVAL 15 DAY gt date modif
  • mysql数据库升级-MySQL 5.7.25主备架构小版本In-Place升级思路

    一 描述 漏扫发现MySQL有低风险漏洞 自己写方案 自己做测试 自己升级 版本 MySQL 5 7 25 升级到MySQL 5 7 28最新版本 架构 主从架构 二 升级流程 1 下载最新版数据库软件MySQL 5 7 28 2 上传到指
  • 萌新的Arduino大作业

    全自动收 晾衣服机 备注 本人因学校社团假期作业要求 用Arduino IDE编写并模拟实现了一个全自动 收 凉衣服的机器 由于硬件条件不足只能模拟 本人也是萌新一枚 希望观看的 大佬们不喜勿喷 有发现做错的话欢迎在评论区讨论 如果对你有帮
  • 西门子编程基础学习分享(3)-数据类型详述

    1200PLC的数据类型详述 前文所提到的数据类型用于描述数据的长度以及属性 即为指定数据元素的大小以及如何解释数据 每个指令至少支持一种数据类型 因而指令上使用的操作数的数据类型必须与指令所支持的数据类型一致 所以在设计程序 建立变量时需
  • Uva 540 Team Queue

    有t个团体的人正在排一个长队 每次新来一个人时 如果这个成员所在的团体已经有人在排队了 那么他就加到最后一个队友身后 如果整个大队列中没有他的团体 那么他就要排在整个大队列的最后 输入每个团队的人数 每个人的编号 要求支持下面的操作 前两种
  • 【订单服务】库存解锁和关单

    消息队列流程图 监听库存解锁 下单成功 库存锁定成功 接下来的业务调用失败 导致订单回滚 之前锁定的库存就要自动解锁 配置队列和交换机 Configuration public class MyRabbitConfig 使用json序列化机
  • 失业在家靠做PPT日赚800-1000元,有一门副业真的很重要!

    下班做PPT 半年挣8万是什么感觉 你好 我是佳佳 一个用PPT兼职挣钱的宝妈 我现在每天抽2个小时 坐在电脑前 把各种素材像拼图一样拼接一下 像这样 然后把成稿投稿到设计平台 就能挣到钱 你是不是觉得 我是个职业设计师 挺厉害的 不是的
  • NLP(十五)让模型来告诉你文本中的时间

    背景介绍 在文章NLP入门 十一 从文本中提取时间 中 笔者演示了如何利用分词 词性标注的方法从文本中获取时间 当时的想法比较简单快捷 只是利用了词性标注这个功能而已 因此 在某些地方 时间的识别效果并不太好 比如以下的两个例子 原文1 苏
  • python递归实现字符串逆反

    def main string input Enter a string string1 reverse string print string s reverse format is string1 def reverse string
  • YOLOV7学习记录之训练过程

    在前面学习YOLOV7的过程中 我们已经学习了其网络结构 然而实际上YOLOV7项目的难点并不在于其网络模型而是在于其损失函数的设计 即如何才能训练出来合适的bbox 神经网络模型都有训练和测试 推理 过程 在YOLOV7的训练过程中 包含
  • Java学习笔记:Java中的加号“+”

    在今晚学习Java时惊奇地发现Java中有 System out println 赋值后c的值为 c 这样的与c语言不同的语法 本着打破砂锅问到底 xue dao si 的精神 稍微整理了一下 下面是整理出来的Java中加号 的用法 算术运
  • mysql字段使用非int做主键,查询时候使用整型和字符串做查询条件的区别

    where条件key是整型的时候也可以找到记录 但是效率慢 不会使用索引 使用字符串的时候会使用主键索引会很快
  • ionic入门教程第十五课-ionic性能优化之图片延时加载

    周五的时候有个朋友让我写一个关于图片延时加载的教程 直到今天才有空编辑 这阶段真的是很忙 公众号都变成僵尸号了 实在是对不起大家 有人喜欢我的教程 可能我总习惯了用比较简单容易理解的方式去描述这些东西 别的就不多说了 大家遇到什么问题 可以
  • 100天精通Python(基础篇)——第23天:while循环 :99乘法表

    i 0 while i lt 10 print 我喜欢你 i 1 print endl i 0 sum 0 while i lt 101 i 1 sum i print f sum sum import random num random
  • django1.10 静态文件配置

    settings配置 网站引用静态文件时都会加上该地址 如 http www xxx com static css mini css STATIC URL static 静态文件根目录 执行命令 python manage py colle
  • PostgreSQL 服务启动不了问题

    配置了postgresql数据的配置文件 pg hba conf后 重记一下服务 结果启动不了 提 示错误 root instance 609xznso run systemctl start postgresql 11 Job for p
  • C++11 function、bind、可变参数模板

    在设计回调函数的时候 无可避免地会接触到可回调对象 在C 11中 提供了std function和 std bind两个方法来对可回调对象进行统一和封装 C 语言中有几种可调用对象 函数 函数指针 lambda表达式 bind创建的对象以及