堆栈溢出与std :: make_unique但不与原始指针

时间:2014-12-07 00:46:04

标签: c++ c++11 heap smart-pointers

我想分配一个大对象(bitset<1000000000>)。由于要避免拥有原始指针,我尝试了以下声明:

auto foo()->std::unique_ptr<std::bitset<MAX>>;
...
{
    auto bar = foo();
}

,它给出了堆栈溢出错误(编译器是VS2013)。但是

auto foo()->std::bitset<MAX>*;
...
{
    auto bar = foo();
    ...
    delete bar;
}

没有。

foo()的实现如下:

auto is_prime = 
        //std::make_unique<std::bitset<MAX>>(std::bitset<MAX>{});
        // or:
        new std::bitset<MAX>{};
is_prime->set();

(*is_prime)[0] = (*is_prime)[1] = false;

auto max_i = static_cast<int>(std::sqrt(MAX)) + 1;
for (auto i = 1; i < max_i; i++) {
        if ((*is_prime)[i]) {
                for (auto j = i * i; j < MAX; j += i) {
                        (*is_prime)[j] = false;
                }
        }
}

return is_prime;

我错过了哪些显而易见的事情?

2 个答案:

答案 0 :(得分:11)

auto is_prime = 
   std::make_unique<std::bitset<MAX>>(std::bitset<MAX>{});

此行在堆栈上创建一个临时bitset对象(std::bitset<MAX>{}),然后将其传递给堆上new ed对象的复制构造函数。

要使用默认构造函数,您需要:

auto is_prime = std::make_unique<std::bitset<MAX>>();

答案 1 :(得分:1)

使用时

typdef std::bitset<1000000> BS;
std::make_unique<BS>(BS())

在堆栈上创建一个相当大的对象:正在复制的临时对象!根据您在tve堆栈上已有多少或堆栈有多大,这可能很容易导致堆栈溢出。对于直接分配内存的操作,没有临时的tge堆栈。

问题的简单解决方法是使用

std::make_unique<BS>()

因为这会导致调用堆分配对象的默认构造函数。