Nodoid
Nodoid

Reputation: 1561

What are the replacements for the smart pointers that existed before Rust 1.0?

I'm updating some old Rust code that used smart pointers and other memory management code that was deprecated and removed prior to the version 1 release.

Is there a direct replacement for the likes of the old smart pointers or is it better to use the likes of Box for allocating memory?

I have code such as (and this is very much simplified!)

struct my_rectangle {
    x: i32,
    y: i32,
    length: i32,
    breadth: i32,
}

fn allocate_rect() {
    let x: ~my_rectangle = ~my_rectangle{x: 5, y: 5, length: 25, breadth:15};
}

and

fn firstMethod() {
    let memblock: @int = @256;
    secondMethod(memblock);
    println!(“%d”,  *memblock);
}

fn secondMethod(memblock: @int) {
    let secMemblock: @int = memblock;
}

This works fine prior to 1.0 but now fails to build.

Upvotes: 3

Views: 271

Answers (3)

Shepmaster
Shepmaster

Reputation: 430663

The other answers cover the principles, so here's your specific examples updated:

struct MyRectangle {
    x: i32,
    y: i32,
    length: i32,
    breadth: i32,
}

fn allocate_rect() {
    Box::new(MyRectangle {
        x: 5,
        y: 5,
        length: 25,
        breadth: 15,
    });
}
use std::rc::Rc;

fn first_method() {
    let memblock = Rc::new(256);
    second_method(memblock.clone());
    println!("{}", memblock);
}

fn second_method(memblock: Rc<isize>) {
    let sec_memblock = memblock;
}
  1. int and uint became isize and usize, respectively. However, you shouldn't just blindly transform these - often times a specific sized integer is better.
  2. Types and traits use CamelCase while functions use snake_case.
  3. There's no need for many type annotations; type inference is very good.
  4. println! no longer uses printf-style format strings. Instead, there are placeholders like {} and {:?} corresponding to traits like Display and Debug.
  5. There's no need to dereference the argument passed to println!.
  6. Calling second_method would transfer ownership of the argument and then you couldn't print it. You need to call clone to increment the reference count and pass the cloned value to the function.

I second the recommendation to evaluate if you really need to box many of these values. In some cases, you may be able to accept a reference or perform a copy of the value (which should be cheap).

Upvotes: 3

Thiez
Thiez

Reputation: 177

You can replace ~T by Box<T>, and ~[T] by Vec<T>. The @T smartpointers can be replaced by Rc<T>, and @[T] by Rc<RefCell<Vec<T>>>. Be careful not to create cycles with Rc<T>, there is no cycle-collector anymore. If the code you wish to update looks anything like the code in your examples, then I would recommend not using pointers at all. ~T (or Box<T>) in particular tends to be overused, and can often be replaced by a simple T.

Upvotes: 3

Francis Gagn&#233;
Francis Gagn&#233;

Reputation: 65742

~T was changed to Box<T>. ~expr should now be Box::new(expr).

@T was removed; it was meant to be a pointer to a garbage-collected object, but that was never really the case. The standard library provides reference-counted pointer, Rc<T> and Arc<T>, that should cover most use cases.

Rust has changed quite a bit until 1.0. You might want to read The Rust Programming Language to get yourself up to date.

Upvotes: 6

Related Questions