临时缓冲区:本地或成员变量?

时间:2014-06-24 10:12:51

标签: c++

在我的课堂上,我有一个需要大型临时缓冲区的方法。我认为有两种方法可以实现这一点:

  • 缓冲区是一个局部变量,并在每次调用函数时静态分配:

    double buf[len];

  • 缓冲区是类的成员变量并分配动态内存(构造或第一次调用)

    this -> buf = new double[len]

第一种方式需要在每次调用时分配内存,但是,我希望堆栈分配非常快。第二种方式定义了一个额外的成员变量,其他方法既不需要也不在方法调用之间持久化,因此不需要是成员变量。

我更喜欢哪一个?

4 个答案:

答案 0 :(得分:4)

您有哪些选择取决于几个问题:

  1. 该函数(可能是间接的)是递归的吗?

  2. 编译时是否知道len

  3. 多个线程可以同时调用该函数吗?在同一个对象上,在不同的对象上,根本不是?

  4. 如果函数不是递归的,则可以使用static局部变量。如果len是编译时常量,static double buf[len];将会执行。对于len的运行时值,请改用static std::vector<double> buf(len);。如果可以进行并发调用,请将thread_local添加到声明中。

    对于递归函数,您必须使用非静态局部变量。如果在编译时知道len,那肯定会非常快(它只是堆栈操作)。如果它是运行时值,则您必须接受每次调用的动态分配(例如std::vector<double> buf(len);),或者创建某种内存池。

答案 1 :(得分:2)

还有第三个选项,即std::vector使用静态存储:

static std::vector<double> buf( len );

这不需要len是编译时常量,而IIRC C ++ 11保证buf的初始化是线程安全的(在C ++ 03中它不能保证虽然)。当然,实际上使用缓冲区将不是线程安全的:您需要某种同步机制(例如互斥锁)或使用线程本地存储分配向量(例如,堆栈或通过一些TLS实现)。

答案 2 :(得分:1)

如果缓冲区长度恒定

线程安全是一个问题吗?如果是这样,那就把它作为一个非静态局部变量放在堆栈上。

如果线程安全不是问题(并且您没有递归使用此函数),那么我建议使用静态局部变量。静态local不会使用无用的字段污染类,也不能在你想要的范围之外访问,而且你只需要分配一次。

如果缓冲区长度不是常数

参见Frerich Raabe的回答。再次注意,如果您使用递归或者期望您的函数一次可能被多个线程使用,静态使用它会有一些问题。

答案 3 :(得分:1)

如果你从多个线程/ recurisvely /任何其他方式调用此函数,那么单例和这些调用需要一个自己的缓冲区使用vector局部变量:

std::vector<double> vec(len);

如果double buf[len];足够大,您的局部变量解决方案(len)将导致堆栈溢出。 (如果len不是编译时常量,标准甚至不允许它,它只是g++扩展名。)

如果每个对象需要一个缓冲区,请使用std::vector成员变量(这实际上与您的第二个解决方案相同,但更多的C ++ ish并自动解除分配。)

struct X {
    std::vector<double> vec;
    X(int len) : vec(len) {}
}

如果您确定您的程序需要一个缓冲区的单个实例,请使用静态版本,作为int @ Frerich的解决方案。

static std::vector<double> buf( len );