c++随笔

1.shared_ptr<void> 和 std::any

#include <iostream>
#include <memory>
#include <any>

using namespace std;

class A {
public:
    A(){
        cout<<"A() is called..."<<endl;
    }
    ~A(){}

    void sayHello(){
        cout<<"sayHello is called..."<<endl;
    }
};

class B : public A
{
public:
    B(){
        cout<<"B() is called..."<<endl;
    }
    ~B(){}
};

int main(int argc, char *argv[])
{
	//1.shared_ptr<void> 和 std::any
    {
        shared_ptr<A> spA = std::make_shared<A>();
        std::cout << "The reference count is: " << spA.use_count() << std::endl;

        std::shared_ptr<void> sp = spA;

        // 输出引用计数
        std::cout << "The reference count is: " << spA.use_count() << std::endl;
        std::cout << "The reference count is: " << sp.use_count() << std::endl;

        // 创建另一个shared_ptr指向同一个对象
        //    std::shared_ptr<A> spA2 = std::dynamic_pointer_cast<A>(sp);//不能是 dynamic_pointer_cast
        std::shared_ptr<A> spA2 = std::static_pointer_cast<A>(sp);

        // 输出引用计数
        std::cout << "The reference count is: " << spA.use_count() << std::endl;
        std::cout << "The reference count is: " << sp.use_count() << std::endl;
        std::cout << "The reference count is: " << spA2.use_count() << std::endl;
    }

    std::cout<<"---------------------------------------------------"<<std::endl;

    {
        shared_ptr<A> spA = std::make_shared<A>();
        std::cout << "The reference count is: " << spA.use_count() << std::endl;

        std::any sp = spA;

        // 输出引用计数
        std::cout << "sp.has_value(): " << sp.has_value() << std::endl;
        std::cout << "The reference count is: " << spA.use_count() << std::endl;

        // 创建另一个shared_ptr指向同一个对象
        std::shared_ptr<A> spA2 = std::any_cast<shared_ptr<A>>(sp);

        // 输出引用计数
        std::cout << "The reference count is: " << spA.use_count() << std::endl;
//        std::cout << "sp.has_value(): " << sp.has_value() << std::endl;
        std::cout << "The reference count is: " << spA2.use_count() << std::endl;
    }
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2.内存顺序

参考:https://www.cnblogs.com/ljmiao/p/18145946

https://blog.csdn.net/lx_ros/article/details/137202294

C++线程编程-内存顺序_c++ 内存序-CSDN博客

https://www.codedump.info/post/20191214-cxx11-memory-model-1/

https://www.codedump.info/post/20191214-cxx11-memory-model-2/

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

3.SFINAE(‌Substitution Failure Is Not An Error)‌是C++编程语言中的一种技术,‌它是一种编译器错误处理机制,‌特别用于模板元编程中12。‌以下是关于SFINAE技术的详细解释:‌

定义

SFINAE意味着当模板实例化过程中发生替换失败时,‌编译器不会将此视为错误,‌而是会简单地忽略该候选模板,‌并继续尝试其他候选模板12。‌这种机制允许编译器在模板实例化过程中更加灵活地处理类型推导和模板重载。‌

工作原理

在模板元编程中,‌当使用模板进行类型推导时,‌C++编译器会尝试对所有可行的候选函数或模板进行匹配,‌并选择最佳的匹配结果。‌如果某个候选函数或模板在类型推导过程中产生了编译错误(‌例如,‌无法推导类型)‌,‌传统情况下编译器会直接报错并中断编译过程。‌然而,‌SFINAE技术允许编译器在遇到这种错误时,‌将错误视为普通的“替代失败”,‌从而继续尝试其他候选函数或模板的匹配1。‌

应用场景

SFINAE技术通常与函数模板的重载和模板参数推导相关。‌通过合理使用SFINAE技术,‌可以实现一些高级的模板元编程技巧,‌比如:‌

  1. 根据类型是否具有某种成员函数来选择不同的模板实现:‌例如,‌可以根据类型是否具有某个成员函数来重载函数模板1。‌
  2. 根据类型是否满足某些条件来进行函数重载或模板特化:‌例如,‌可以根据类型是否为整数类型、‌指针类型或类类型来选择不同的函数模板或模板特化实现12。‌

示例

以下是一个使用SFINAE技术的示例,‌展示了如何根据类型是否为整数类型来重载函数模板1:‌

template<typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type foo(T value) {
    // 处理整数类型的情况
}

template<typename T>
typename std::enable_if<!std::is_integral<T>::value, void>::type foo(T value) {
    // 处理非整数类型的情况
}

在这个示例中,‌std::enable_if是一个类型特征工具,‌它根据条件(‌这里是类型T是否为整数类型)‌来选择性地启用或禁用函数模板。‌

注意事项

  • SFINAE技术在C++11标准之后得到了进一步的改进和扩展,‌引入了std::enable_if类型特征工具和变量模板等,‌使得SFINAE更加方便和灵活1。‌
  • 使用SFINAE技术时,‌需要注意其可能带来的复杂性,‌特别是在处理复杂的模板重载和特化时6。‌

结论

SFINAE是C++模板元编程中一个非常有用的技术,‌它允许编译器在模板实例化过程中更加灵活地处理类型推导和模板重载。‌通过合理使用SFINAE技术,‌可以实现更加灵活和高效的代码。‌然而,‌也需要注意其可能带来的复杂性,‌并谨慎使用。‌

参考:https://zhuanlan.zhihu.com/p/688452093

+++++++++++++++++++++++++++++++++++++++++++++++

4.scp相关

在shell脚本中,${variable%%pattern}的语法用于从variable的末尾删除与variable的末尾删除与variable的末尾删除与pattern匹配的最长字符串。‌ 这被称为模式匹配的"最长匹配"操作。具体到问题中的${SSH_CLIENT%% *},这里的%%用于从$SSH_CLIENT变量的值中删除最长匹配的空格及其后面的所有字符,即删除IP地址后的任何额外字符(如果有的话),通常用于提取IP地址。

例如,如果$SSH_CLIENT的值是"192.168.1.100 59000 52623",那么${SSH_CLIENT%% *}将会返回"192.168.1.100",即IP地址部分。这是因为%%操作符从字符串的末尾开始查找与空格及其后面的所有字符匹配的模式,并将其删除。

这种模式匹配在shell脚本中非常有用,尤其是在处理字符串和提取特定信息时。通过使用不同的模式匹配操作符(如#和%),可以灵活地处理和提取字符串的不同部分‌

-------------------

~$ str="abc,def,ghi,obq"
~$ echo ${str%%,*}            //从最前面开始找符合",*"的并删除之后的内容后返回
abc
~$ echo ${str%,*}            //从最后面开始找符合",*"的并删除之后的内容后返回
abc,def,ghi

-------------------

~$ ssh root@192.168.1.11

~$ echo ${SSH_CLIENT}
192.168.1.11 53642 22

~$ echo ${SSH_CLIENT%%}
192.168.1.11 53642 22

~$ echo ${SSH_CLIENT%% *}
192.168.1.11

-------------------
cd
vim .bashrc
s2c(){scp "$@" ${SSH_CLIENT%% *}:~/;}
c2s(){scp ${SSH_CLIENT%% *}:"$@" .;}
c2s2(){scp ${SSH_CLIENT%% *}:/upload/* .;}

source .bashrc

+++++++++++++++++++++++++++++++++++++++++++++++

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值