学习随笔(更新中,想到哪写到哪)

本文介绍了线性代数中向量空间的维度与矩阵维度的区别,解释了网桥、网关、路由和交换机在网络通信中的作用,以及ARP协议在路由器寻址中的重要性。此外,还讨论了C++中智能指针的实现,包括构造函数、赋值运算符和移动语义的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.线性代数的一些概念的内容

向量空间的维度是由基向量个数决定的,同时(a,b,c),(a,b,c,d)也决定了此时向量空间分别为三维空间和四维空间,只是这时(a,b,c),(a,b,c,d)代表了该空间中的一个点。

矩阵维度和向量空间维度没有关系,矩阵维度由线性无关的向量个数决定的

[1,2,1]

[2,4,3]

[1,2,7] 

并不是三维矩阵,而是二维矩阵。

2.网桥,网关,路由,交换机的区别和联系

网关通常只能处理局域网和互联网之间的数据传输,而无法处理不同局域网之间的数据传输。比如局域网Ⅰ就无法和局域网Ⅳ通信,因为网关里没有在不断更新的路由表,路由表是ARP之类的协议在路由器之间不断更新的。

这时就需要使用路由器,路由器可以连接不同的网络,并根据路由表将数据包从一个网络转发到另一个网络。路由器在互联网上多次跳跃找到目标网络。

网桥只能处理两个局域网之间的通信,如果区域内超过两个局域网需要通信了,也需要一个路由器接一下,约等于互联网但是范围要小的多。

同一个局域网之内通过一个交换机用MAC地址最终定位设备。

网络协议概览:

当一个路由器需要将报文发送到另一个网络时,它首先需要将报文封装成一个 IP 数据报,并将目标主机的 IP 地址作为目的地地址。然后,路由器会根据路由表中的信息找到报文的下一跳路由器,并将 IP 数据报发送给下一跳路由器。

在这个过程中,路由器需要使用 IP 协议来进行路由选择,使用 ICMP 协议来进行网络故障的诊断和错误报告,以及使用 OSPF 协议交换路由信息。在完成路由选择后,路由器会根据下一跳路由器的 MAC 地址将 IP 数据报转发给下一跳路由器。这一过程中,路由器会使用 ARP 协议解析下一跳路由器的 MAC 地址。
 

路由器在转发数据包时,需要在数据链路层使用 MAC 地址来寻址,以便在本地网络中将数据包转发给正确的下一跳路由器或目标主机。因此,当路由器需要将数据包转发到另一个网络时,它需要知道下一跳路由器的 MAC 地址,以便将数据包正确地发送到下一跳路由器。

有一个问题是,一般说路由转发都是IP协议的事,为什么这里提到了ARP协议也应用在路由器寻址上了。

因为IP协议只在网络层上寻址,数据要从应用层一层层封装,传到路由器再一层层的拆,所以封完网络层的目的IP之后还要再封数据链路层的目的MAC地址,这就要求完全在物理层发出去之前,即使是路由也还是需要下一跳目的地址的。

IP 协议只负责在网络层上将数据包从源主机路由到目标主机,而不涉及 MAC 地址的使用。因此,即使路由器知道下一跳路由器的 IP 地址,也无法直接将数据包发送到下一跳路由器,必须先将 IP 数据包封装成数据链路层帧,并将目标 MAC 地址设置为下一跳路由器的 MAC 地址。

在这种情况下,路由器需要使用 ARP(Address Resolution Protocol)协议来获取下一跳路由器的 MAC 地址。当路由器收到一个数据包时,它会检查数据包的目标 IP 地址,并查看它的 ARP 缓存表中是否有与该 IP 地址对应的 MAC 地址。如果没有,路由器就会使用 ARP 协议来获取目标主机的 MAC 地址。

3.智能指针摘要

template<typename T>
class SmartPtr {
public:
///第一部分//
    explicit SmartPtr(T* ptr = nullptr) : m_ptr(ptr) {}
    ~SmartPtr() { delete m_ptr; }

    SmartPtr(const SmartPtr& other) = delete; // 禁止复制构造函数
    SmartPtr& operator=(const SmartPtr& other) = delete; // 禁止赋值运算符
/

第二部分/
    SmartPtr(SmartPtr&& other) noexcept : m_ptr(other.m_ptr) { other.m_ptr = nullptr; }
    SmartPtr& operator=(SmartPtr&& other) noexcept {
        if (this != &other) {
            delete m_ptr;
            m_ptr = other.m_ptr;
            other.m_ptr = nullptr;
        }
        return *this;
    }


//第三部分///
    T* operator->() const { return m_ptr; }
    T& operator*() const { return *m_ptr; }
    operator bool() const { return m_ptr != nullptr; }
/

private:
    T* m_ptr;
};

以上是智能指针最简化版的实现,可以分为三个部分方便立即理解

第一部分是最基本的构造函数和析构函数,但是最关键的地方是在第一部分用=delete的形式禁用了拷贝构造函数和赋值运算符,这样有效避免了多个智能指针共享同一个资源。=delete是C++11的新关键字,可以禁用某一个成员函数。

第二部分是通过右值引用完成移动构造函数和移动赋值运算符完成资源的转换。非常明显的特征是函数参数用了两个&&说明这是右值引用,右值引用多用于资源的直接转移,避免发生拷贝和内存分配的操作,noexcept是告诉编译器这一部分不需要抛出异常,因为这里只是简单的转移出现异常肯定不是在这里出问题的。

所以第二部分的主要功能就是用右值引用作为参数重载了拷贝构造函数和赋值运算符。

可能有人会问,为什么在第一部分禁止了赋值运算符,第二部分又重载一个赋值运算符,直接拿第二部分的

SmartPtr& operator=(SmartPtr&& other)

隐藏掉第一部分被禁止SmartPtr & operator=()的不就行了。虽然问题有点嘚逼,但是我之前还真想过这个问题。因为有这个问题的人是把隐藏和重载搞混了,同一个类里面的成员函数没有隐藏这一说法的,隐藏不了的,禁止是禁止的事,重载是重载的事,以后有需要的话还得再禁止几个或者再重载几个不同参数的赋值运算符。

第三部分就是重载一些最常用的指针运算符了

*运算符是最简单取值运算符的,不用多谈。有人会问重载的->干什么用的。好像用不到啊。

先额外说一下值得注意的是智能指针因为禁用了赋值运算符,初始化智能指针最常用的是用new运算符和C++14以后的make_unique<>或make_share<>

所以对于智能指针来说,example 1里赋值a的地址的代码会报错的。只能通过example 2的方式完成初始化。当你new的是int,float这种基本类型,->操作符是没用的。但是如果智能指针作为类指针的话,比如example 3里,需要用->运算符调用类的成员。

/example 1//
int a=42;
int *p=&a;


/example 2//
SmartPtr<int>ptr(new int(42));



example 3/
#include <iostream>
#include <memory>

class MyClass {
public:
   
    void print() { std::cout << "Hello from MyClass!" << std::endl; }
};

int main() {
    std::unique_ptr<MyClass> ptr1(new MyClass);
    std::unique_ptr<MyClass> ptr2;
    ptr2->print(); // 输出 "Hello from MyClass!"

    ptr2 = move(ptr1); // 移动赋值操作
    return 0;
}
///

那么又有人了问了,例1里赋值运算符都用不了了,我之前重载的赋值运算符干嘛去了?

答案是用在了转移智能指针资源的move方法里了,可以看见ptr2=move(ptr1)时用到“=”这个运算符。

下面再给一个unique_ptr的简单实现,比最简单的smart指针多了一些内容,防止面试的时候问到 了。

template<typename T>
class unique_ptr {
public:
    explicit unique_ptr(T* ptr = nullptr) : m_ptr(ptr) {}
    ~unique_ptr() { delete m_ptr; }

    unique_ptr(const unique_ptr&) = delete; // 禁止复制构造函数
    unique_ptr& operator=(const unique_ptr&) = delete; // 禁止赋值运算符

    unique_ptr(unique_ptr&& other) noexcept : m_ptr(other.m_ptr) { other.m_ptr = nullptr; }
    unique_ptr& operator=(unique_ptr&& other) noexcept {
        if (this != &other) {
            delete m_ptr;
            m_ptr = other.m_ptr;
            other.m_ptr = nullptr;
        }
        return *this;
    }

    T* operator->() const { return m_ptr; }
    T& operator*() const { return *m_ptr; }
    operator bool() const { return m_ptr != nullptr; }

    T* get() const { return m_ptr; }
    T* release() noexcept {
        T* temp = m_ptr;
        m_ptr = nullptr;
        return temp;
    }

    void reset(T* ptr = nullptr) {
        if (m_ptr != ptr) {
            delete m_ptr;
            m_ptr = ptr;
        }
    }

private:
    T* m_ptr;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值