In C++, new operation can fail and either return a null pointer or throw a std::bad_alloc exception, which depends on what new function you called. I wondered if there's similar feature in Rust, for example a version of Box/Arc returns a Result?
P.S. I can do this in unsafe code with alloc, but I do want to use Box/Arc in this case.
I suddenly have a question, may out of topic. We normally create a Box like this:
let box = Box::new(Foo::new());
In this way, won't the program do an extra copy from the stack to the heap? Is there anything we can do other than expecting the compiler to do the optimization? As far as I know, new_in_place or placement new is still in discussion and have a long time until we can use it.
If you have a Foo::new_uninit() function available, you can similarly use a Vec trick to avoid a manual alloc():
pub fn new_foo_in_place() -> Box<Foo> {
let mut vec = Vec::with_capacity(1);
// SAFETY: We call `set_len` after initializing the element.
unsafe {
Foo::new_uninit(&mut vec.spare_capacity_mut()[0]);
vec.set_len(1);
}
let ptr = Box::into_raw(vec.into_boxed_slice());
// SAFETY: We go from a length-1 `Box<[T]>` to a `Box<T>`.
unsafe { Box::from_raw(ptr.cast()) }
}
// or, a bit more precariously:
use std::mem::ManuallyDrop;
pub fn new_foo_in_place() -> Box<Foo> {
let ptr: *mut Foo = ManuallyDrop::new(Vec::with_capacity(1)).as_mut_ptr();
unsafe {
Foo::new_uninit(&mut *ptr.cast::<MaybeUninit<Foo>>());
Box::from_raw(ptr)
}
}