前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >还得是GPT-4o真强呀:单例模式在libsrt中的运用

还得是GPT-4o真强呀:单例模式在libsrt中的运用

作者头像
手撕代码八百里
发布2024-05-24 13:14:44
1000
发布2024-05-24 13:14:44
举报
文章被收录于专栏:猿计划猿计划

比较好奇libsrt库的socket通讯如何实现的,就随意翻了翻socket通讯部分的代码,发现了一些技巧,特此记录。

libsrt库主要由C++开发的,看:

个别的是.c文件。

libsrt库的examples中的test-c-client.c和test-c-server.c共同组成了一个简单的srt客户端和server端:

只要是写过socket的,这些再简单不过了。

追踪:

继续追:

发现通讯部分都是调用的uglobal().xxxx();

没看uglobal()函数之前,疯狂的猜测: 1、难道是x实现的? 2、难道是xx实现的? 3、难道是xxx实现的?

看了代码才知道,原来用到了单例模式:

言归正传:

如果是Java的话,最常见单例模式的如下所写:

代码语言:javascript
复制
public class SingleTon {
	private static final SingleTon instance = new SingleTon();
	private SingleTon() {
	}
	public static SingleTon getInstance(){
		return instance;
	}
}

libsrt中C++的单例这样写的:

代码语言:javascript
复制
CUDTUnited& srt::CUDT::uglobal()
{
    static CUDTUnited instance;
    return instance;
}

这段代码就是实现了一个超级简单的单例,还运用了一个C++的特性:函数内的静态局部变量。

这段代码主要是把这个特性给整明白就可以了,我还有GPT-4o都觉得有如下好处:

  • 1、延迟初始化:局部静态变量只在函数首次被调用时初始化。这意味着如果从未调用该函数,实例也不会被创建。这在某些情况下可以节省资源和时间,因为不需要在程序开始时就创建单例实例。
  • 2、线程安全:从C++11开始,C++标准保证局部静态变量的初始化是线程安全的。也就是说,即使在多线程环境下,也只有一个线程能够初始化该变量,其他线程将等待初始化完成。这确保了单例模式在多线程环境中的安全性。
  • 3、控制实例化时机:因为实例是在函数第一次调用时创建的,所以程序员可以更精确地控制实例化的时机。这对一些需要依赖其他组件初始化的单例实例尤其重要。
  • 4、简化代码和封装:将静态变量声明在函数内部,可以将实例的创建和访问逻辑封装在一个地方,简化代码结构,使代码更加模块化和易于维护。

GPT-4o

请GPT-4o老师生成一个示例,展示为什么将静态变量写在函数内部更有优势:

代码语言:javascript
复制
#include <iostream>
#include <mutex>

// Singleton class example
class CUDTUnited {
public:
    // Public method to access the singleton instance
    static CUDTUnited& getInstance() {
        static CUDTUnited instance; // Local static instance
        return instance;
    }

    void connect(int u, const char* name, int namelen, bool forced_isn) {
        std::cout << "Connecting: " << name << std::endl;
    }

private:
    // Private constructor to prevent instantiation
    CUDTUnited() { std::cout << "CUDTUnited instance created." << std::endl; }

    // Delete copy constructor and assignment operator
    CUDTUnited(const CUDTUnited&) = delete;
    CUDTUnited& operator=(const CUDTUnited&) = delete;
};

// Usage example
void exampleUsage() {
    CUDTUnited& instance = CUDTUnited::getInstance();
    instance.connect(1, "example", 7, true);
}

int main() {
    exampleUsage();
    exampleUsage(); // The instance will not be created again
    return 0;
}

在上述代码中:

首次调用 getInstance 时,会输出 “CUDTUnited instance created.” 和 “Connecting: example”。 再次调用 exampleUsage 时,只会输出 “Connecting: example”,因为实例只会被创建一次。

对比:"函数外部静态变量"如果将静态变量写在函数外部,无法享受上述所有的好处,例如:

代码语言:javascript
复制
#include <iostream>

// Singleton instance declared outside of the function
static CUDTUnited instance; // Will be created at program startup

class CUDTUnited {
public:
    static CUDTUnited& getInstance() {
        return instance;
    }

    void connect(int u, const char* name, int namelen, bool forced_isn) {
        std::cout << "Connecting: " << name << std::endl;
    }

private:
    CUDTUnited() { std::cout << "CUDTUnited instance created." << std::endl; }
    CUDTUnited(const CUDTUnited&) = delete;
    CUDTUnited& operator=(const CUDTUnited&) = delete;
};

void exampleUsage() {
    CUDTUnited& instance = CUDTUnited::getInstance();
    instance.connect(1, "example", 7, true);
}

int main() {
    exampleUsage();
    exampleUsage(); // The instance will not be created again
    return 0;
}

在这种情况下:

程序启动时,无论是否使用 CUDTUnited 实例,都会创建实例。这可能会浪费资源。 线程安全问题:需要手动保证多线程环境下的线程安全,增加代码复杂性。

因此,将静态变量写在函数内部是单例模式实现的一种推荐方法,特别是从C++11开始,它提供了更好的延迟初始化和线程安全支持。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • GPT-4o
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档