2011-11-02 47 views
3
class MyString 
{ 
    public: 
    MyString(int length):_ptr(alloca(length)) 
    { 
    } 
    //Copy Constructor, destructor, other member functions. 
    private: 
    void* _ptr; 
}; 

int main() 
{ 
    MyString str(44); 
    return 0; 
} 

它是否在主函数的末尾释放或者在构造函数执行后立即释放? 如果上述代码按预期工作,是否有像这样的字符串类是一个好主意?何时使用alloca为类成员释放内存?

更新:

它看起来像主要的危险是

  1. StackOverflow的
  2. 构造的内联

我想我可以用ALLOCA为照顾StackOverflow上的小尺寸和malloc /免费的大尺寸。我想必须有一些非可移植的编译器特定的方式来强制编译器内联。

我很感兴趣,因为字符串类是在任何c + +项目中广泛使用的东西。如果我明白了这一点,我预计会有巨大的性能提升,因为大部分分配都会进入堆栈,否则会进入堆栈。这将是一个实用程序,最终用户不会意识到内部。

+3

这取决于您选择的优化级。它只在构造函数内联时才起作用。不要使用这个。 –

回答

5

根据alloca的文档,当alloca的调用者返回时,内存被释放。因此,如果初始化列表被编译器视为构造函数的一部分,即在执行初始化列表之前创建了堆栈帧,那么将在构造函数的末尾释放内存。如果在初始化列表执行后创建了堆栈框架,则分配的内存将位于构造函数的调用者中,因此在这种情况下,内存将在main的末尾释放。我不知道这个标准足以确定它会发生哪种方式。

但是,只要内存最终被释放,ptr的值将保持不变。

+1

+1我认为* initializer list *是在构造函数的栈帧中处理的,因为它可能位于不同的翻译单元中,编译器不可能知道它必须在调用构造函数之前分配额外的空间*。 –

+0

@DavidRodríguez - dribeas:绝对。至少从实现的角度来看,初始化器的构造代码是在父c'tor – valdo

+0

的范围内执行的,所以即使构造器总是内联,它也不会工作? – balki

3

当然,类成员的初始化是作为c'tor的一部分执行的。因此,至少按照标准,由alloca返回的指针的有效性仅限于c'tor。

因此,按照您的方式初始化您的班级成员似乎是一个非常糟糕的主意。

OTOH会有用以下没有问题:

class MyString 
{ 
    public: 
    MyString(void* ptr):_ptr(ptr) 
    { 
    } 
    //Copy Constructor, destructor, other member functions. 
    private: 
    void* _ptr; 
}; 

int main() 
{ 
    MyString str(alloca(44)); 
    return 0; 
}