C++ 禁止自动初始化和销毁

标签 c++ initialization destructor

如何抑制类型的自动初始化和销毁​​? T buffer[100] 自动初始化 buffer 的所有元素,并在它们超出范围时销毁它们,这很棒,但这不是我想要的行为。

#include <iostream>

static int created   = 0,
           destroyed = 0;

struct S
{
    S()
    {
        ++created;
    }
    ~S()
    {
        ++destroyed;
    }
};

template <typename T, size_t KCount>
class fixed_vector
{
private:
    T m_buffer[KCount];
public:
    fixed_vector()
    {
        // some way to suppress the automatic initialization of m_buffer
    }

    ~fixed_vector()
    {
        // some way to suppress the automatic destruction of m_buffer
    }
};

int main()
{
    {
        fixed_vector<S, 100> arr;
    }

    std::cout << "Created:\t"   << created   << std::endl;
    std::cout << "Destroyed:\t" << destroyed << std::endl;
    return 0;
}

这个程序的输出是:

Created:    100
Destroyed:  100

我希望它是:

Created:    0
Destroyed:  0

我唯一的想法是使 m_buffer 成为一些像 char 这样简单构造和破坏的类型,然后依靠 operator[] 来包装指针数学对我来说,虽然这似乎是一个可怕的黑客解决方案。另一种解决方案是使用 mallocfree,但这提供了我不想要的间接级别。


我想要这个的原因是因为我正在制作一个容器,我不想为我不会使用的东西支付初始化开销。例如,如果我的 main 函数是:

int main()
{
    {
        std::vector<S> vec;
        vec.reserve(50);
    }

    std::cout << "Created:\t"   << created   << std::endl;
    std::cout << "Destroyed:\t" << destroyed << std::endl;
    return 0;
}

输出是正确的:

Created:    0
Destroyed:  0

最佳答案

你可能想看看 boost::optional

template <typename> struct tovoid { typedef void type; };

template <typename T, size_t KCount, typename = void>
struct ArrayStorage {
  typedef T type;
  static T &get(T &t) { return t; }
};

template <typename T, size_t KCount>
struct ArrayStorage<T, KCount, typename tovoid<int T::*>::type> {
  typedef boost::optional<T> type;
  static T &get(boost::optional<T> &t) {
    if(!t) t = boost::in_place();
    return *t;
  }
};

template <typename T, size_t KCount>
class Array
{
public:
    T &operator[](std::ptrdiff_t i) {
      return ArrayStorage<T, KCount>::get(m_buffer_[i]);
    }

    T const &operator[](std::ptrdiff_t i) const {
      return ArrayStorage<T, KCount>::get(m_buffer_[i]);
    }

    mutable typename ArrayStorage<T, KCount>::type m_buffer_[KCount];
};

对类类型进行了专门化,将它们包装到一个optional中,从而延迟调用构造函数/析构函数。对于非类类型,我们不需要包装。不包装它们意味着我们可以将 &a[0] 视为连续的内存区域,并将该地址传递给需要数组的 C 函数。 boost::in_place 将就地创建类类型,而不使用临时的 T 或其复制构造函数。

不使用继承或私有(private)成员允许类保持聚合,允许一种方便的初始化形式

// only two strings are constructed
Array<std::string, 10> array = { a, b };

关于C++ 禁止自动初始化和销毁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2662417/

相关文章:

c++ - 有条件的平凡析构函数

c++ - 显式调用析构函数

c++ - 静态存储持续时间对象的破坏和未定义的行为

c++ - 如何获得指向颜色按钮的指针

c - 使用 CUBLAS/CUSPARSE 操作将统一数组的元素设置为 0 是否安全?

c++ - Boost message_queue : just the constructor lets me configure it, 无其他成员函数可用

c++ - 为什么 std::unique_ptr 重置与赋值不同?

c++ - 这是什么模板?

C++ 专门针对特定类型的 lambda

c++ - 如何初始化静态类的疙瘩成语的d(指针)?