我有一些代码使用可变长度数组(VLA),它在gcc和clang中编译得很好,但不适用于MSVC 2015。
class Test {
public:
Test() {
P = 5;
}
void somemethod() {
int array[P];
// do something with the array
}
private:
int P;
}
代码中似乎有两个解决方案:
vector
成员变量(假设只要P在构造对象后保持不变,vector和c数组之间的开销不是限制因素) ector将更具可移植性(少#ifdef
测试使用哪个编译器),但我怀疑alloca()
更快。
矢量实现如下所示:
class Test {
public:
Test() {
P = 5;
init();
}
void init() {
array.resize(P);
}
void somemethod() {
// do something with the array
}
private:
int P;
vector<int> array;
}
另一个考虑因素:当我只在函数外部更改P时,堆上有一个数组,而不是比堆栈上的VLA更快地重新分配?
最大P约为400。
答案 0 :(得分:3)
您可以并且可能应该使用一些动态分配的heap内存,例如由std::vector管理(如answered by Peter)。您可以使用智能指针或纯粹的原始指针(new
,malloc
,....),您不应忘记发布(delete
,free
,... ..)。请注意,堆分配可能比您所认为的快(实际上,大多数情况下,当前笔记本电脑的分配时间远远小于1微秒)。
有时你可以将分配从一些内循环中移出,或者偶尔增长它(对于realloc
类似的东西,更好地使用unsigned newsize=5*oldsize/4+10;
而不是unsigned newsize=oldsize+1;
即具有一些几何增长)。如果你不能使用向量,请确保保持单独的分配大小和使用的长度(如std::vector
在内部)。
另一种策略是针对特殊情况小尺寸和大尺寸。例如对于少于30个元素的数组,使用调用堆栈;对于较大的,请使用堆。
如果您坚持在[{3}}上分配(使用VLA - 他们是标准C ++ 11或alloca
的常用扩展名,那么明智地限制您的调用帧到几千字节。总呼叫栈受限于某些实现特定限制(例如,在许多笔记本电脑上经常为大约一兆字节或几个)。在某些操作系统中,您可以提高该限制(另请参阅Linux上的call stack)
确保在手动调整代码之前进行基准测试。在进行基准测试之前,不要忘记启用setrlimit(2)(例如g++ -O2 -Wall
和compiler optimization)。请记住,GCC通常比堆分配贵得多。不要忘记,开发人员的时间也有一些成本(通常与累积的硬件成本相当)。
请注意,使用caches misses或数据也存在问题(不是static variable,不是reentrant安全,不是async-signal-safe -see thread ... 。)并且可读性较差且不太稳健。
答案 1 :(得分:3)
首先,如果您的代码按原样编译任何C ++编译器,那么您就会很幸运。 VLA不是标准C ++。 Some compilers支持他们作为扩展。
使用alloca()
也不是标准的,因此在使用不同的编译器时不能保证可靠(甚至根本不能)工作。
在许多情况下,使用static
向量是不可取的。在您的情况下,它提供的行为可能与原始代码不同。
您可能希望考虑的第三个选项是
// in definition of class Test
void somemethod()
{
std::vector<int> array(P); // assume preceding #include <vector>
// do something with array
}
向量本质上是一个动态分配的数组,但在函数返回时将在上面正确清理。
以上是标准C ++。除非您进行严格的测试和分析,以提供性能问题的证据,否则这应该足够了。
答案 2 :(得分:1)
为什么不将数组作为私有成员?
const template: Electron.MenuItemConstructorOptions[] = [{
label: 'Edit',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
{ role: 'pasteandmatchstyle' },
{ role: 'delete' },
{ role: 'selectall' }
]
},
{
label: 'View',
submenu: [
{ role: 'reload' },
{ role: 'forcereload' },
{ role: 'toggledevtools' },
{ type: 'separator' },
{ role: 'resetzoom' },
{ role: 'zoomin' },
{ role: 'zoomout' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
},
{ role: 'window', submenu: [{ role: 'minimize' }, { role: 'close' }] },
{
role: 'help',
submenu: [{
label: 'Learn More',
click() {
require('electron').shell.openExternal('https://electron.atom.io');
}
}]
}
];
由于您已经指定了数组的最大可能大小,您还可以查看boost::small_vector
之类的内容,可以像以下一样使用:
#include <vector>
class Test
{
public:
Test()
{
data_.resize(5);
}
void somemethod()
{
// do something with data_
}
private:
std::vector<int> data_;
}
您应该剖析以确定这是否真的更好,并且请注意这可能会占用更多内存,如果有许多#include <boost/container/small_vector.hpp>
class Test
{
public:
Test()
{
data_.resize(5);
}
void somemethod()
{
// do something with data_
}
private:
using boc = boost::container;
constexpr std::size_t preset_capacity_ = 400;
boc::small_vector<int, preset_capacity_> data_;
}
个实例,这可能是一个问题。