Fonction d'allocation de mémoire C ++ std :: calloc ()

Fonction: void * calloc (size_t num, size_t size); num est le nombre d'éléments et size est la longueur en octets de chaque élément.
Le fichier d'en-tête malloc.h
alloue n espaces continus de taille de taille dans la zone de stockage dynamique de la mémoire. La fonction renvoie un pointeur vers l'adresse de départ de l'allocation; si l'allocation échoue, elle renvoie NULL.

Utilisé pour obtenir un espace de tableau, l'élément de tableau est initialisé à 0.

Utilisez généralement free (pointeur de l'adresse de départ) pour libérer la mémoire après utilisation.
La différence avec malloc: après que
calloc alloue dynamiquement de la mémoire, il initialise automatiquement l'espace mémoire à zéro, tandis que malloc ne s'initialise pas et les données à l'intérieur sont des données aléatoires.

calloc peut être utilisé pour allouer des tableaux dynamiques, tels que:

#include <memory>
#include <iostream>

int main()
{
    double* arrPtr;
    size_t num=5;
    arrPtr = (double*)calloc(num,sizeof(double));

    for(int i=0;i<5;++i)
        std::cout<<&arrPtr[i]<<" "<<arrPtr[i]<<std::endl;

    free(arrPtr);

    return 0;
}

std :: calloc () peut également être utilisé pour l'allocation mémoire de la classe:

Par exemple, allouez un tableau dynamique pour stocker l'objet fonction std :: function <> class

#include <malloc.h>
#include <iostream>
#include <functional>

using namespace std;

int a = 100;
int b = 15;

int addFun()
{
    return a + b;
}

int subtrFunc()
{
    return a -b;
}

int multiFun()
{
    return a*b;
}

float deviFun()
{
    return (float)a/b;
}

int modFun()
{
    return a%b;
}

int main()
{
    std::function<int()>* taskQueue;
    size_t size=16;
    size_t num=5;
    taskQueue=(std::function<int()>*)calloc(num,sizeof(std::function<int()>));

    std::function<int()> callback1 = std::bind(addFun);
    std::cout<<"callback size:"<<sizeof(callback1)<<std::endl;
    taskQueue[0] = callback1;

    std::function<int()> callback2 = std::bind(subtrFunc);
    std::cout<<"callback size:"<<sizeof(callback2)<<std::endl;
    taskQueue[1] = callback2;

    std::function<int()> callback3 = std::bind(multiFun);
    std::cout<<"callback size:"<<sizeof(callback3)<<std::endl;
    taskQueue[2] = callback3;

    std::function<int()> callback4 = std::bind(deviFun);
    std::cout<<"callback size:"<<sizeof(callback4)<<std::endl;
    taskQueue[3] = callback4;

    std::function<int()> callback5 = std::bind(modFun);
    std::cout<<"callback size:"<<sizeof(callback5)<<std::endl;
    taskQueue[4] = callback5;

    for(int i = 0;i < num; ++i)
    {
        std::cout<<taskQueue[i]()<<std::endl;
    }

    free(taskQueue);
    return 0;
}

L'implémentation du pool de threads dans Apollo utilise formellement la méthode ci-dessus pour définir un pool de pointeurs vers un tableau dynamique, spécifier la taille du tableau lors de l'initialisation et allouer de la mémoire. Le tableau dynamique est utilisé pour enregistrer dynamiquement la file d'attente des tâches.

template <typename T>
class BoundedQueue {
 public:
  using value_type = T;
  using size_type = uint64_t;

 public:
  BoundedQueue() {}
  BoundedQueue& operator=(const BoundedQueue& other) = delete;
  BoundedQueue(const BoundedQueue& other) = delete;
  ~BoundedQueue();
  bool Init(uint64_t size);
  bool Init(uint64_t size, WaitStrategy* strategy);
  bool Enqueue(const T& element);
  bool Enqueue(T&& element);
  bool WaitEnqueue(const T& element);
  bool WaitEnqueue(T&& element);
  bool Dequeue(T* element);
  bool WaitDequeue(T* element);
  uint64_t Size();
  bool Empty();
  void SetWaitStrategy(WaitStrategy* WaitStrategy);
  void BreakAllWait();
  uint64_t Head() { return head_.load(); }
  uint64_t Tail() { return tail_.load(); }
  uint64_t Commit() { return commit_.load(); }

 private:
  uint64_t GetIndex(uint64_t num);

  alignas(CACHELINE_SIZE) std::atomic<uint64_t> head_ = {0};
  alignas(CACHELINE_SIZE) std::atomic<uint64_t> tail_ = {1};
  alignas(CACHELINE_SIZE) std::atomic<uint64_t> commit_ = {1};
  // alignas(CACHELINE_SIZE) std::atomic<uint64_t> size_ = {0};
  uint64_t pool_size_ = 0;
  T* pool_ = nullptr; //指向数组的指针,数组容器里面保存的是T*类型
  std::unique_ptr<WaitStrategy> wait_strategy_ = nullptr;
  volatile bool break_all_wait_ = false;
};

...

template <typename T>
bool BoundedQueue<T>::Init(uint64_t size, WaitStrategy* strategy) {
  // Head and tail each occupy a space
  pool_size_ = size + 2;
  pool_ = reinterpret_cast<T*>(std::calloc(pool_size_, sizeof(T)));
  if (pool_ == nullptr) {
    return false;
  }
  for (uint64_t i = 0; i < pool_size_; ++i) {
    new (&(pool_[i])) T();
  }
  wait_strategy_.reset(strategy);
  return true;
}

...
template <typename T>
BoundedQueue<T>::~BoundedQueue() {
  if (wait_strategy_) {
    BreakAllWait();
  }
  if (pool_) {
    for (uint64_t i = 0; i < pool_size_; ++i) {
      pool_[i].~T();
    }
    std::free(pool_); //释放的时候不需要for循环释放
  }
}

 

Je suppose que tu aimes

Origine blog.csdn.net/sunlin972913894/article/details/105927200
conseillé
Classement