我想分配一个大对象(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;
我错过了哪些显而易见的事情?
答案 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>()
因为这会导致调用堆分配对象的默认构造函数。