27

目前我执行以下操作:

// float *c_array = new float[1024];

void Foo::foo(float *c_array, size_t c_array_size) {
  //std::vector<float> cpp_array;

  cpp_array.assign(c_array, c_array + c_array_size);
  delete [] c_array;
}

如何优化此分配?我不想执行元素复制,而只是交换指针。

4

5 回答 5

24

当前std::vector不提供任何功能或接口来获取先前分配的存储的所有权。据推测,意外传递堆栈地址太容易了,导致问题多于解决的问题。

如果您想避免复制到向量中,则需要在整个调用链中使用向量,或者float[]在整个时间内以 C 方式进行。你不能混合它们。您可以保证这&vec[0]将等同于 C 数组,完全连续,因此在整个程序中使用向量可能是可行的。

于 2011-04-29T19:29:53.000 回答
6

目前,该std::vector接口不具备移动或交换除另一个之外的任何东西的能力std::vector

于 2011-04-29T19:22:40.493 回答
5

唯一的方法是创建一个自定义分配器。

  1. 编写一个分配器类,您可以使用您的数组对其进行初始化。

  2. 使用分配器作为参数实例化向量。

于 2011-04-29T21:27:42.927 回答
1

不太可能 - 这是非常危险的,因为 std::vector 不知道内存是如何分配的以及应该如何释放它。

如果可能,您可以用创建正确大小的 std::vector 来替换原始分配。它使用连续的内存区域,因此可以代替手动分配的缓冲区。

于 2011-04-29T19:27:48.443 回答
0

可以使用自定义分配器。我用 clang 和 gcc 检查了 godbolt.org。对我来说,它看起来有点丑陋——但它至少可以作为概念证明。

当然,您必须自己照顾阵列的生命周期。

#include <vector>
#include <iostream>

// custom allocator
template <typename T>
class my_allocator {
  private:
    T* const addr;
  public:
    template <typename U>
    struct rebind {
      typedef my_allocator<U> other;
    };

    //provide the required no-throw constructors / destructors:
    constexpr my_allocator(T* addr_) : addr(addr_) { };
    constexpr my_allocator(const my_allocator<T>& rhs) : addr(rhs.addr) { };
    template <typename U>
    my_allocator(const my_allocator<U>& rhs, T* addr_) : addr(addr_) { };
    ~my_allocator()  { };

    //import the required typedefs:
    using value_type=T;
    using pointer=T*;
    using reference=T&;
    using const_pointer=const T*;
    using const_reference=const T&;
    using size_type=size_t;
    using difference_type=ptrdiff_t;

  constexpr pointer   allocate(size_type n, const void * = 0) {
              pointer t=addr;
              std::cout
              << "  used my_allocator to allocate   at address "
              << t << " (+)" << std::endl;
              return addr;
            }

    constexpr void      deallocate(void* p, size_type) {
        if (p) {
        std::cout
        << "  used my_allocator to deallocate at address "
        << p << " (-)" << 
        std::endl;
        } 
    }

    template< class U, class... Args >
    void construct( U* p, Args&&... args ) {
        // avoids initialisation of the elements.
        std::cout << "Contruct called" << std::endl;
    }

};

// helper function for easy useage
template<typename T>
const std::vector<T, my_allocator<T> > CreateVectorFromArray(T* array, int size) {
    const my_allocator<T> alloc=my_allocator<T>(array);
    std::vector<int, my_allocator<int> > vecAll(size, my_allocator<int>(array));
    return vecAll;
}

template<typename T>
using element_type_t = std::remove_reference_t<decltype(*std::begin(std::declval<T&>()))>;

template<typename AR>
auto CreateVectorFromArrayAr(AR& array) {
    using T=element_type_t<AR>;
    const my_allocator<T> alloc=my_allocator<T>(array);
    std::vector<T, my_allocator<T> > vecAll(sizeof(array)/sizeof(array[0]), my_allocator<T>(array));
    return vecAll;
}

int main() {
    int array[]={0,1,2,3,4,5,6,7,8,9};
    std::cout << "Array:  " << &array[0] << " " << array[0]  << " " << array[1]<< " " << array[2] << std::endl;

    auto vecAll=CreateVectorFromArray(array, sizeof(array)/sizeof(array[0]));
    auto vec3=CreateVectorFromArrayAr(array);


    std::cout << "Vector: " << &vecAll[0] << " " << vecAll[0] << " " << vecAll[1]<< " " << vecAll[2] << std::endl;
    std::cout << "Array:  " << &array[0] << " " << array[0]  << " " << array[1] << " " << array[2] << std::endl;
    std::cout << "vec3:   " << &vec3[0] << " " << vec3[0]  << " " << vec3[1] << " " << vec3[2] << std::endl;
    std::cout << "sizeof(vecAll)=" << sizeof(vecAll) << std::endl;
    std::cout << "sizeof(void*)=" << sizeof(void*) << std::endl;
    return 0;
}
于 2021-09-16T22:47:07.280 回答