【问题标题】:Compile time method to determine whether object has automatic storage duration编译时间方法判断对象是否具有自动存储时长
【发布时间】:2013-10-15 08:07:09
【问题描述】:

我希望能够在编译时强制特定类型只能用于创建具有自动存储持续时间的对象。

template<typename T, typename Alloc>
struct Array
{
    T* data; // owned resource
    Array(std::size_t size); // allocates via Alloc
    ~Array(); // deallocates via Alloc
};

typedef Array<int, AutoAllocator<int>> AutoArray;

void foo(AutoArray a) // ok
{
    AutoArray l = AutoArray(); // ok
    static AutoArray s; // error
    new AutoArray(); // error
    std::vector<AutoArray> v(1); // error
}

此应用程序可以为AutoArray 实例所拥有的资源选择最佳分配策略。这个想法是具有自动存储持续时间的对象所需的资源分配模式与 LIFO 资源分配器兼容。

在 C++ 中我可以使用什么方法来实现这一点?

编辑:次要目标是通过放入AutoAllocator 或默认std::allocator 来透明地切换Array 的分配策略。

typedef Array<int, std::allocator<int>> DynamicArray;

假设有大量代码已经使用DynamicArray

【问题讨论】:

  • 您可以将operator new 声明为私有,但不确定是否可以阻止静态对象。
  • +1,好问题,但我认为没有办法做到这一点。
  • @LuchianGrigore 我正在使用对象的构造函数/析构函数来分配其拥有的资源。具有静态存储持续时间的局部变量会预先分配空间,但问题是它们不是按照与 LIFO 兼容的顺序构造的。
  • @LuchianGrigore 将operator new 声明为private 并不会停止堆分配,因为您可以改写::new EnforceAuto
  • @willj 你可能想多了。您可以简单地添加评论。 :)

标签: c++ memory-management stack metaprogramming


【解决方案1】:

这是无法做到的。考虑您创建了一个将其作为成员的类型。当编译器为该类型的构造函数生成代码时,它不知道对象是在哪里创建的,完整的对象是否在堆栈中,是否在堆中?

您需要用不同的思维方式解决您的问题,例如,您可以将分配器传递给对象的构造函数(BSL 所做的方式)并可能默认为安全分配器(基于 new-delete ),然后对于那些使用 lifo 分配器是更好的选择的用例,用户可以显式请求它。

这与编译器错误不同,但它足够明显,可以在代码审查中检测到。

如果您真的对分配器的有趣用途感兴趣,您可能想看看标准库的 BSL 替代品,因为它允许传播到容器成员的多态分配器。在 BSL 世界中,您的示例将变为:

// Assume a blsma::Allocator implementing LIFO, Type uses that protocol
LifoAllocator alloc;       // implements the bslma::Allocator protocol
Type l(&alloc);            // by convention bslma::Allocator by pointer
static Type s;             // defaults to new-delete if not passed
new (&alloc) Type(&alloc); // both 'Type' and it's contents share the allocator
                           // if the lifetime makes sense, if not:
new Type;                  // not all objects need to use the same allocator
bsl::vector<Type> v(&alloc);
v.resize(1);               // nested object uses the allocator in the container

通常使用分配器并不简单,您必须注意对象之间以及相对于分配器的相对生命周期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-14
    • 2014-04-04
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 2016-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多