最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++通用動(dòng)態(tài)抽象工廠的實(shí)現(xiàn)詳解

 更新時(shí)間:2022年07月12日 09:25:57   作者:用戶2471098440237  
在面向?qū)ο蟮木幊讨?一般通過繼承和虛函數(shù)來提供抽象能力,下面這篇文章主要給大家介紹了關(guān)于C++通用動(dòng)態(tài)抽象工廠的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

背景

一開始,我是想到了下面這個(gè)場景:

struct A {
  void Foo() {}
};

struct B {
  void Bar() {
    A().Foo();
  }
};

如上面代碼,B的Bar中構(gòu)造了A,然后調(diào)用了A的Foo函數(shù)。假如我想在別的場景中復(fù)用B的Bar,但是這時(shí)A的Foo就不符合需求了,需要定制,于是我們想到可以用多態(tài),把A的Foo改成虛函數(shù),然后寫出A1:

struct A {
  A() = default;
  virtual ~A() = default;
  virtual void Foo() {}
};

struct A1 : public A {
  void Foo() override {}
};

B不應(yīng)該知道A1的存在,為了讓B用上A1,同時(shí)也為以后可能會(huì)拓展的A2、A3做準(zhǔn)備,我們寫了個(gè)A的工廠函數(shù)GetA()來生成A。于是代碼變成:

std::unique_ptr<A> GetA() {
  if (Condition1()) {
    return std::unique_ptr<A>(new A1());
  } else {
    return std::unique_ptr<A>(new A());
  }
}

struct B {
  void Bar() {
    GetA()->Foo();
  }
};

如果B中還要構(gòu)造別的C、D等類,難道我們要為每個(gè)類都寫一個(gè)工廠函數(shù)嗎?這成本也太高了,而且可能大部分類都只有一個(gè),不用搞繼承,寫工廠函數(shù)就是無用功。那么,有沒有一種通用的方式可以在寫B(tài)代碼的時(shí)候就對A、C、D等類的構(gòu)造都留一手,使得以后可以由B外的代碼控制實(shí)際構(gòu)造的是A1等,而不需要修改B的代碼?這就是我寫動(dòng)態(tài)抽象工廠的原始需求。

實(shí)現(xiàn)

思路很簡單,就是為每個(gè)類都自動(dòng)生成一個(gè)工廠函數(shù)就好了,然后在B中不直接構(gòu)造A、C、D等對象,而是都調(diào)用對應(yīng)類的工廠函數(shù)。然后這個(gè)自動(dòng)生成的工廠默認(rèn)就是構(gòu)造原始的類的對象,比如A,也有接口可以改成生成子類,比如A1。對每個(gè)類生成一個(gè)工廠函數(shù)自然就想到用模板了。至于這個(gè)接口怎么實(shí)現(xiàn),就有兩大分支,分別是編譯期和運(yùn)行期。編譯期一般就是用模板特化了。我覺得運(yùn)行期會(huì)更有趣,用法會(huì)更多,就選了運(yùn)行期。

運(yùn)行期的意思就是要搞個(gè)變量來存下這個(gè)修改的工廠函數(shù),自然就想到用std::function。當(dāng)然免不了的是要把這個(gè)變量傳給B。如果管理A的是一個(gè)變量,管理C、D的是另外兩個(gè)變量,那就要傳很多很多變量給B,這樣也太繁瑣了,所以應(yīng)該一個(gè)變量存下所有類的工廠函數(shù),然后把這個(gè)變量傳遍所有需要使用工廠函數(shù)的對象或函數(shù)當(dāng)中。所以這個(gè)變量的類型是一個(gè)確定的類型,不能帶模板(或者說模板參數(shù)不能跟工廠對應(yīng)的類相關(guān),如A、C、D等)。那么模板就放到方法當(dāng)中了。很自然地,這個(gè)類型的接口就應(yīng)該是這樣:

struct DynamicAbstractFactory {
  template <typename T, typename... Args>
  std::unique_ptr<T> New(Args&&...);
};

這里插一段,為什么叫動(dòng)態(tài)抽象工廠呢?按照我的理解,工廠模式就是實(shí)現(xiàn)一個(gè)返回T*的函數(shù)F,里面用ifelse來控制最終返回的是T還是T的某個(gè)子類。抽象工廠模式就是連這個(gè)函數(shù)F都是可變的。動(dòng)態(tài)是指這個(gè)F是運(yùn)行時(shí)可變。

那么這個(gè)接口怎么實(shí)現(xiàn)呢?我的想法是用一個(gè)map來記錄類型組合(T, Args&&...)到工廠函數(shù)std::function<T*(Args&&...)>的映射,并存儲(chǔ)std::function<T*(Args&&...)>。New的實(shí)現(xiàn)就是查找map中有沒有對應(yīng)的工廠函數(shù),有就調(diào)用工廠函數(shù),沒有就調(diào)用T本身的構(gòu)造函數(shù)。當(dāng)然,也需要提供一個(gè)接口來修改這個(gè)map。

要實(shí)現(xiàn)這個(gè)map還有三個(gè)細(xì)節(jié):

  • 存儲(chǔ)的std::function<T*(Args&&...)>是不同的類型,需要用類型擦除存儲(chǔ)。如果可用C++17的話可直接用std::any,但我的環(huán)境有些老代碼用gcc7編不過,所以還是只能用C++11,于是用std::shared_ptr<void>來代替(我一開始還是用std::unique_ptr+虛析構(gòu)函數(shù)+繼承來實(shí)現(xiàn)的,后來才知道std::shared_ptr自帶這個(gè)功能)。
  • map的key是一個(gè)類型組合,就用std::type_index吧。由于std::function<T*(Args&&...)>已經(jīng)把整個(gè)類型組合包進(jìn)去了,而且一定會(huì)實(shí)例化,就直接用它吧。于是key就成了std::type_index(typeid(std::function<T*(Args&&...)>))。
  • 由于接口New(Args&&...)的每個(gè)參數(shù)類型Args&&都是引用類型,為了保持一致性,為了map能找到正確的函數(shù),要求std::function中的每個(gè)參數(shù)也是引用類型,所以上面都寫作std::function<T*(Args&&...)>。比如std::function<T*(int)>會(huì)轉(zhuǎn)換成std::function<T*(int&&)>。

再加上修改map的接口SetFunc,第一版的動(dòng)態(tài)抽象工廠就做好了:

class DynamicAbstractFactory {
 public:
  template <typename T, typename... Args>
  std::unique_ptr<T> New(Args&&... args) {
    auto iter = index2func_.find(std::type_index(typeid(std::function<T*(Args&&...)>)));
    if (iter != index2func_.end()) {
      return std::unique_ptr<T>((*reinterpret_cast<std::function<T*(Args&&...)>*>(iter->second.get()))(std::forward<Args>(args)...));
    }
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  }

  template <typename T, typename... Args>
  void SetFunc(std::function<T*(Args...)>&& func) {
    index2func_[std::type_index(typeid(std::function<T*(Args&&...)>))] = std::make_shared<std::function<T*(Args&&...)>>(std::move(func));
  }

 protected:
  std::unordered_map<std::type_index, std::shared_ptr<void>> index2func_;
};

于是B的代碼及使用就變成這樣:

class B {
 public:
  B(DynamicAbstractFactory& factory) : factory_(factory) {}
  void Bar() {
    factory_.New<A>()->Foo();
    factory_.New<C>();
    factory_.New<D>();
  }
 protected:
  DynamicAbstractFactory& factory_;
};

// 舊環(huán)境,用原始A、C、D
// 當(dāng)然B也可以用factory來生成
void Run() {
  DynamicAbstractFactory factory;
  factory.New<B>(factory)->Bar();
}

// 新環(huán)境,用A1、C、D
void Run1() {
  DynamicAbstractFactory factory;
  std::function<A*()> get_a = []() {
    return new A1();
  };
  factory.SetFunc<A>(std::move(get_a));
  factory.New<B>(factory)->Bar();
}

這樣就滿足了一開始的需求,B在構(gòu)造A、C、D的時(shí)候都留了一手,B并不需要知道實(shí)際構(gòu)造的是什么,在B的外部,Run()和Run1(),可控制在B里具體要構(gòu)造的對象。

寫完后發(fā)現(xiàn)這東西作用不止于此,下面寫寫一些擴(kuò)展用法。

寄存參數(shù)

子類的構(gòu)造函數(shù)的參數(shù)可以跟父類不一樣,通過lambda捕獲來寄存。

struct A2 : public A {
  A2(int i) {}
  void Foo() override {}
};

void Run2() {
  DynamicAbstractFactory factory;
  int i = 0;
  std::function<A*()> get_a = [i]() {
    return new A2(i);
  };
  factory.SetFunc<A>(std::move(get_a));
  factory.New<B>(factory)->Bar();
}

存儲(chǔ)所有構(gòu)造出來的對象

上面的接口返回std::unique_ptr,還要管理對象生命周期,不如更進(jìn)一步,用factory來管理所有它構(gòu)造的對象,在factory析構(gòu)時(shí)統(tǒng)一析構(gòu)。因?yàn)槲乙话銓懞笈_(tái)rpc接口,可以在rpc請求開始時(shí)構(gòu)造factory,在構(gòu)造好回包后析構(gòu)factory,這樣在整個(gè)請求周期構(gòu)造的對象都在,指針不會(huì)失效,而且在請求結(jié)束后可以很方便地進(jìn)行異步析構(gòu),直接把factory丟到析構(gòu)線程就好。

于是New接口返回值由std::unique_ptr改成T*,同時(shí)New可能會(huì)造成誤解,改成Get。當(dāng)然,存儲(chǔ)肯定要用到類型擦除存儲(chǔ)。就成了下面這樣:

class GeneralStorage {
 public:
  GeneralStorage(size_t reserve_size = 256) {
    storage_.reserve(reserve_size);
  }
  ~GeneralStorage() {
    // 保證按添加順序逆序析構(gòu)
    while (storage_.size() > 0) {
      storage_.pop_back();
    }
  }

  template <class T, class... Args>
  T* EmplaceBack(Args&&... args) {
    auto p_obj = std::make_shared<T>(std::forward<Args>(args)...);
    storage_.push_back(p_obj);
    return p_obj.get();
  }

 protected:
  std::vector<std::shared_ptr<void>> storage_;
};

class DynamicAbstractFactoryWithStorage {
 public:
  template <typename T, typename... Args>
  T* Get(Args&&... args) {
    auto iter = index2func_.find(std::type_index(typeid(std::function<T*(Args&&...)>)));
    if (iter != index2func_.end()) {
      return (*reinterpret_cast<std::function<T*(Args&&...)>*>(iter->second.get()))(std::forward<Args>(args)...);
    }
    return storage_.EmplaceBack<T>(std::forward<Args>(args)...));
  }

  template <typename T, typename... Args>
  void SetFunc(std::function<T*(Args...)>&& func) {
    index2func_[std::type_index(typeid(std::function<T*(Args&&...)>))] = std::make_shared<std::function<T*(Args&&...)>>(std::move(func));
  }

 protected:
  std::unordered_map<std::type_index, std::shared_ptr<void>> index2func_;
  GeneralStorage storage_; 
};

有個(gè)細(xì)節(jié)是對于改變過的工廠函數(shù)返回的指針是不應(yīng)該存在storage_中的,而應(yīng)該是在工廠函數(shù)中把對象存進(jìn)storage_。上面的Run1()應(yīng)該改成這樣:

void Run1() {
  DynamicAbstractFactoryWithStorage factory;
  std::function<A*()> get_a = [&factory]() {
    return factory.Get<A1>();
  };
  factory.SetFunc<A>(std::move(get_a));
  factory.Get<B>(factory)->Bar();
}

寄存指針,可析構(gòu)的單例

當(dāng)返回值由std::unique_ptr改成T*,就可以實(shí)現(xiàn)寄存指針了??晌鰳?gòu)的單例指每次請求都重新構(gòu)造,在請求結(jié)束后析構(gòu),但是請求之中只構(gòu)造一次??聪旅胬樱?/p>

struct C {
  C(DynamicAbstractFactoryWithStorage& factory) {
    std::function<C*(DynamicAbstractFactoryWithStorage&)> func = [this](DynamicAbstractFactoryWithStorage& factory) {
      return this;
    };
    factory.SetFunc<C>(std::move(func));
  }
};

void Run() {
  DynamicAbstractFactoryWithStorage factory;
  factory.Get<C>(factory); // 構(gòu)造C,并通過SetFunc把對象的指針寄存到factory中
  factory.Get<C>(factory); // 調(diào)用C構(gòu)造函數(shù)中的func,直接返回寄存的指針,不重復(fù)構(gòu)造C
  // factory析構(gòu)時(shí)C的對象將被析構(gòu)
}

裝飾工廠函數(shù),責(zé)任鏈工廠

只要再加個(gè)接口GetFunc來獲取當(dāng)前的工廠函數(shù),就可以對工廠函數(shù)玩裝飾模式了。

GetFunc接口:

// 其它代碼與上面一樣
class DynamicAbstractFactoryWithStorage {
 public:
  template <typename T, typename... Args>
  std::function<T*(Args&&...)> GetFunc() {
    auto iter = index2func_.find(std::type_index(typeid(std::function<T*(Args&&...)>)));
    if (iter != index2func_.end()) {
      return *reinterpret_cast<std::function<T*(Args&&...)>*>(iter->second.get());
    }
    std::function<T*(Args&&...)> default_func = [this](Args&&... args) {
      return storage_.EmplaceBack<T>(std::forward<Args>(args)...));
    };
    return default_func;
  }
};

統(tǒng)計(jì)調(diào)用次數(shù):

struct C {
  C(DynamicAbstractFactoryWithStorage& factory) {
    std::function<C*(DynamicAbstractFactoryWithStorage&)> func = [this](DynamicAbstractFactoryWithStorage& factory) {
      return this;
    };
    factory.SetFunc<C>(std::move(func));
  }

  uint32_t cnt_ = 0;
};

void Run() {
  DynamicAbstractFactoryWithStorage factory;
  auto func = factory.GetFunc<A>();
  std::function<A*()> get_a = [func, &factory]() {
    ++factory.Get<C>()->cnt_;
    return func();
  };
  factory.SetFunc<A>(std::move(get_a));
  factory.Get<B>(factory)->Bar();
}

用責(zé)任鏈模式搞個(gè)工廠:

struct D {
  D() {}
  D(int i) {}
};

struct D1 : public D {
  D1(int i) {}

  static void SetFactoryD(DynamicAbstractFactoryWithStorage& factory) {
    // GetFunc的結(jié)果是std::fuction<D*(int&&)>類型的,這里經(jīng)過了一次類型轉(zhuǎn)換
    std::function<D*(int)> func = factory.GetFunc<D, int>();
    std::function<D*(int)> new_func = [func, &factory](int i) -> D* {
      // 責(zé)任鏈模式
      if (Check(i)) {
        return factory.Get<D1>(i);
      } else {
        return func(i);
      }
    };
    factory.SetFunc<D>(std::move(new_func));
  }

  // 構(gòu)造D1的條件
  static bool Check(int i) {
    return i == 1;
  }
};

// 與D1類似,除了Check
struct D2 : public D {
  D2(int i) {}

  static void SetFactoryD(DynamicAbstractFactoryWithStorage& factory) {
    std::function<D*(int)> func = factory.GetFunc<D, int>();
    std::function<D*(int)> new_func = [func, &factory](int i) -> D* {
      if (Check(i)) {
        return factory.Get<D2>(i);
      } else {
        return func(i);
      }
    };
    factory.SetFunc<D>(std::move(new_func));
  }

  // 構(gòu)造D2的條件
  static bool Check(int i) {
    return i == 2;
  }
};

void Run() {
  DynamicAbstractFactoryWithStorage factory;
  D1::SetFactoryD(factory);
  D2::SetFactoryD(factory);
  factory.Get<D>(0); // D
  factory.Get<D>(1); // D1
  factory.Get<D>(2); // D2
}

允許構(gòu)造函數(shù)之外的參數(shù)組合

上面的實(shí)現(xiàn)要求new T(std::forward(args)...)能合法生成一個(gè)T對象指針,在一些情況下很難做到,比如T中有難以初始化的成員,又比如T是一個(gè)抽象類:

struct E {
  E() = default;
  virtual ~E() = default;
  virtual void Foo() = 0;
};

這樣就要修改Get接口的邏輯,改成如果能合法調(diào)用構(gòu)造函數(shù),就調(diào)用,否則就不調(diào)用。但是這樣放開之后,就各種參數(shù)組合都可以搞了,我覺得這樣可能會(huì)很混亂,這邊設(shè)置了這個(gè)參數(shù)組合,那邊設(shè)置了另外的參數(shù)組合,不知道一共設(shè)置了哪幾種參數(shù)組合。我覺得還是要加點(diǎn)限制,就規(guī)定參數(shù)組合必須在基類中定義。規(guī)定了一個(gè)方法名FactoryGet,所有非構(gòu)造函數(shù)的參數(shù)組合要定義一個(gè)靜態(tài)FactoryGet方法,方法返回T*,比如:

struct E {
  E() = default;
  static E* FactoryGet(int) {
    return nullptr;
  }
  virtual ~E() = default;
  virtual void Foo() = 0;
};

這樣Get接口的邏輯就可以改成如果能合法調(diào)用構(gòu)造函數(shù),就調(diào)用,否則就調(diào)用對應(yīng)的FactoryGet方法,其他參數(shù)組合將會(huì)編譯報(bào)錯(cuò)。同時(shí)也規(guī)定FactoryGet獲得的指針不存進(jìn)通用存儲(chǔ)。于是DynamicAbstractFactoryWithStorage就改成這樣:

// new T(std::forward<Args>(args)...)
// T::FactoryGet(std::forward<Args>(args)...)
// 要求上面兩個(gè)表達(dá)式有且僅有一個(gè)合法并且返回T*,Get調(diào)用合法的那個(gè)。
template <typename T, typename F, typename = void>
struct DefaultGet;

template <typename T, typename... Args>
struct DefaultGet<T, void(Args...), typename std::enable_if<std::is_same<decltype(std::decay<T>::type::FactoryGet(std::forward<Args>(*reinterpret_cast<typename std::decay<Args>::type*>(0))...)), T*>::value, void>::type> {
  static T* Get(GeneralStorage& storage, Args&&... args) {
    return T::FactoryGet(std::forward<Args>(args)...);
  }
};

template <typename T, typename... Args>
struct DefaultGet<T, void(Args...), typename std::enable_if<std::is_same<decltype(new typename std::decay<T>::type(std::forward<Args>(*reinterpret_cast<typename std::decay<Args>::type*>(0))...)), typename std::decay<T>::type*>::value, void>::type> {
  static T* Get(GeneralStorage& storage, Args&&... args) {
    return storage.EmplaceBack<typename std::decay<T>::type>(std::forward<Args>(args)...);
  }
};

class DynamicAbstractFactoryWithStorage {
 public:
  // 每個(gè)Args都要是引用
  template <typename T, typename... Args>
  using FuncType = std::function<T*(Args&&...)>;

  template <typename T, typename... Args>
  T* Get(Args&&... args) {
    auto iter = index2func_.find(std::type_index(typeid(FuncType<T, Args...>)));
    if (iter != index2func_.end()) {
      return (*reinterpret_cast<FuncType<T, Args...>*>(iter->second.get()))(std::forward<Args>(args)...);
    }
    return DefaultGet<T, void(Args&&...)>::Get(storage_, std::forward<Args>(args)...);
  }

  template <typename T, typename... Args>
  void SetFunc(std::function<T*(Args...)>&& func) {
    index2func_[std::type_index(typeid(FuncType<T, Args...>))] = std::make_shared<FuncType<T, Args...>>(std::move(func));
  }

  template <typename T, typename... Args>
  FuncType<T, Args...> GetFunc() {
    auto iter = index2func_.find(std::type_index(typeid(FuncType<T, Args...>)));
    if (iter != index2func_.end()) {
      return *reinterpret_cast<FuncType<T, Args...>*>(iter->second.get());
    }
    FuncType<T, Args...> default_func = [this](Args&&... args) {
      return DefaultGet<T, void(Args&&...)>::Get(storage_, std::forward<Args>(args)...);
    };
    return default_func;
  }

 protected:
  std::unordered_map<std::type_index, std::shared_ptr<void>> index2func_;
  GeneralStorage storage_;
};

這樣E就能像上面那樣用了。另外,想要返回const指針也是可以的。

struct E {
  E() = default;
  // 返回值改成了const E*
  static const E* FactoryGet(int) {
    return nullptr;
  }
  virtual ~E() = default;
  virtual void Foo() = 0;
};

struct E1 : public E {
  E1(int i) {}
  static void SetFactoryE(DynamicAbstractFactoryWithStorage& factory) {
    std::function<const E*(int)> func = factory.GetFunc<const E, int>();
    std::function<const E*(int)> new_func = [func, &factory](int i) -> const E* {
      if (Check(i)) {
        return factory.Get<const E1>(i);
      } else {
        return func(i);
      }
    };
    factory.SetFunc<const E>(std::move(new_func));
  }
  static bool Check(int i) {
    return i == 1;
  }

  void Foo() override {}
};

void Run() {
  DynamicAbstractFactoryWithStorage factory;
  E1::SetFactoryE(factory);
  factory.Get<const E>(0); // nullptr
  factory.Get<const E>(1); // const E1*
}

總結(jié)

到此這篇關(guān)于C++通用動(dòng)態(tài)抽象工廠的文章就介紹到這了,更多相關(guān)C++通用動(dòng)態(tài)抽象工廠內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言之平衡二叉樹詳解

    C語言之平衡二叉樹詳解

    平衡二叉樹是具有平衡屬性的有序二叉樹,本文主要介紹了C語言中的平衡二叉樹,具有一定的參考價(jià)值,需要的小伙伴可以參考閱讀
    2023-04-04
  • 關(guān)于STL中的map容器的一些總結(jié)

    關(guān)于STL中的map容器的一些總結(jié)

    對于map的學(xué)習(xí),或者說是對STL中的容器的學(xué)習(xí),要知道每種容器的實(shí)現(xiàn)原理,每種適合適合解決什么問題的,才是關(guān)鍵
    2013-09-09
  • 用C語言實(shí)現(xiàn)從文本文件中讀取數(shù)據(jù)后進(jìn)行排序的功能

    用C語言實(shí)現(xiàn)從文本文件中讀取數(shù)據(jù)后進(jìn)行排序的功能

    這是一個(gè)十分可靠的程序,這個(gè)程序的查錯(cuò)能力非常強(qiáng)悍。程序包含了文件操作,歸并排序和字符串輸入等多種技術(shù)。對大家學(xué)習(xí)C語言很有幫助,有需要的一起來看看。
    2016-08-08
  • opencv3/C++ 實(shí)現(xiàn)SURF特征檢測

    opencv3/C++ 實(shí)現(xiàn)SURF特征檢測

    今天小編就為大家分享一篇opencv3/C++ 實(shí)現(xiàn)SURF特征檢測,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • Qt數(shù)據(jù)庫應(yīng)用之實(shí)現(xiàn)通用數(shù)據(jù)庫采集

    Qt數(shù)據(jù)庫應(yīng)用之實(shí)現(xiàn)通用數(shù)據(jù)庫采集

    這篇文章主要為大家介紹了Qt中是如何實(shí)現(xiàn)通用數(shù)據(jù)庫采集的,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Qt有一定幫助,感興趣的小伙伴可以了解一下
    2022-03-03
  • C語言編程動(dòng)態(tài)內(nèi)存分配常見錯(cuò)誤全面分析

    C語言編程動(dòng)態(tài)內(nèi)存分配常見錯(cuò)誤全面分析

    這篇文章主要介紹了C語言編程中動(dòng)態(tài)內(nèi)存分配的常見錯(cuò)誤全面分析講解,同樣遇到過C語言動(dòng)態(tài)內(nèi)存分配各種問題的同學(xué)可以借鑒參考下,希望能夠有所幫助
    2021-10-10
  • Qt?事件處理機(jī)制的深入理解

    Qt?事件處理機(jī)制的深入理解

    本文主要介紹了Qt?事件處理機(jī)制的深入理解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 教你5分鐘輕松搞定內(nèi)存字節(jié)對齊

    教你5分鐘輕松搞定內(nèi)存字節(jié)對齊

    隨便google一下,人家就可以跟你解釋的,一大堆的道理,我們沒怎么多時(shí)間,討論為何要對齊.直入主題,怎么判斷內(nèi)存對齊規(guī)則,sizeof的結(jié)果怎么來的,請牢記以下3條原則
    2013-09-09
  • OpenMP中For Construct對dynamic的調(diào)度方式詳解

    OpenMP中For Construct對dynamic的調(diào)度方式詳解

    在本篇文章當(dāng)中主要給大家介紹 OpenMp for construct 的實(shí)現(xiàn)原理,與他相關(guān)的動(dòng)態(tài)庫函數(shù)分析以及對 dynamic 的調(diào)度方式進(jìn)行分析,希望對大家有所幫助
    2023-02-02
  • 超詳細(xì)解析C++實(shí)現(xiàn)歸并排序算法

    超詳細(xì)解析C++實(shí)現(xiàn)歸并排序算法

    歸并排序是比較穩(wěn)定的排序方法。它的基本思想是把待排序的元素分解成兩個(gè)規(guī)模大致相等的子序列。本文將用C++實(shí)現(xiàn)這一排序算法,需要的可以參考一下
    2022-09-09

最新評論

墨江| 阳东县| 哈巴河县| 晋城| 罗定市| 翁牛特旗| 获嘉县| 武胜县| 泽州县| 五台县| 雅安市| 香格里拉县| 彭阳县| 宜兰市| 深水埗区| 开封县| 禹城市| 赤壁市| 黑山县| 浙江省| 武平县| 宁波市| 汪清县| 富宁县| 融水| 开原市| 北宁市| 额敏县| 顺义区| 长岛县| 镶黄旗| 高青县| 含山县| 嘉义县| 容城县| 昌平区| 桂阳县| 香河县| 金华市| 筠连县| 浙江省|