make_shared与自定义新运算符 [英] make_shared with custom new operator

查看:137
本文介绍了make_shared与自定义新运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是重复的,但我在任何地方找不到解决方案。

This is probably a duplicate, but I cannot find the solution anywhere.

我有这样的源代码:

struct Blob{
    //...    

    static void *operator new(size_t size_reported, size_t size) {
        return ::operator new(size);
    }
};

我这样使用:

std::shared_ptr<Blob> blob;
// ...
size_t size = calcSize(); // it returns say 231
Blob *p = new(size) Blob();
blob.reset(p);

我可以改变代码,所以我可以使用 std :: make_shared std :: allocate_shared 所以我有单个分配,而不是两个分配

Can I change the code somehow so I can use std::make_shared or std::allocate_shared so I have single allocation instead of two allocations?

我能够消除 new 并将代码简化为以下内容:

I was able to eliminate the new and simplify the code to the following:

struct Blob{
    //...    
};

std::shared_ptr<Blob> blob;
// ...
size_t size = calcSize(); // it returns say 231

// allocate memory
void *addr = ::operator new(size);

// placement new
Blob *p = ::new(addr) Blob();

blob.reset(p);

它完全一样的东西,但我想现在更清楚我试图do。

It does exactly the same thing, but I think now it is more clear what I'm trying to do.

推荐答案

这里是最新动态。

没有办法将大小传递给allocator,可以通过全局变量类成员来执行。

Since there is no way to pass size to the allocator, you can do it via global variable or class member.

在这两种情况下,解决方案根本不优雅,相当危险 - 灾难等待发生,现在或以后当代码需要维护。

In both cases the solution is not elegant at all and is rather dangerous - disaster waiting to happen now or later when code needs to be maintained.

如果 allocate_shared shared_ptr 控制块缓冲区类。

Another unexpected problem may happen if allocate_shared place the shared_ptr control block after the buffer class.

在这种情况下会有清除缓冲区溢出,因为 sizeof(buffer)会报告大小,所以。

In such case there will be clear buffer overflow, because sizeof(buffer) will report size like 1 byte or so.

再次 - 代码正常工作,但是将来会有问题。

Once again - the code is working, but will have issues in the future for sure.

#include <stdio.h>
#include <string.h>

#include <memory>

// ============================

class buffer{
public:
    buffer(const char *s){
        strcpy(x, s);
    }

    char x[1];
};

// ============================

template <typename T>
struct buffer_allocator {
    using value_type = T;

    buffer_allocator() = default;

    template <class U>
    buffer_allocator(const buffer_allocator<U>&) {}

    T* allocate(size_t n) {
        void *p = operator new(n * sizeof(T));

        printf("Allocate   %p, (%zu)\n", p, get_size());

        return (T*) p;
    }

    void deallocate(T* p, size_t n) {
        delete p;

        printf("Deallocate %p, (%zu)\n", p, get_size());
    }

    size_t get_size(){
        return size;
    }

    void set_size(size_t size){
        this->size = size;
    }

private:
    size_t size = 0;
};

template <typename T, typename U>
inline bool operator == (const buffer_allocator<T>&, const buffer_allocator<U>&) {
  return true;
}

template <typename T, typename U>
inline bool operator != (const buffer_allocator<T>& a, const buffer_allocator<U>& b) {
  return !(a == b);
}

// ============================

int main(int argc, char *argv[]){
    buffer_allocator<buffer> ba;

    const char *s = "hello world!";

    ba.set_size( strlen(s) + 1 );

    auto b = std::allocate_shared<buffer>(ba, s);

    printf("Pointer    %p\n", b.get());

    printf("%s\n", b->x);
    printf("%zu\n", b.use_count());
    auto b1 = b;
    printf("%zu\n", b1.use_count());

    return 0;
}

这篇关于make_shared与自定义新运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆