# How to better use pointers?

**URL:** <https://discourse.julialang.org/t/how-to-better-use-pointers/68433>\
**Category:** General Usage\
**Created:** [September 20, 2021, 5:45am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433 "2021-09-20T05:45:03Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [September 20, 2021, 5:45am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/1 "2021-09-20T05:45:03Z")

</div>

I love pointers, but there are limited functions in julia.

| C/C++ | Julia |
| --- | --- |
| `p=&a` | `p=pointer_from_objref(a)` |
| `a=*p` | `a=unsafe_pointer_to_objref(p)` |
| `*p=3` | how? |
| `p->x=3` | how? |
| `p->tab["a"]=3` | how? |
| etc. | |

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [September 20, 2021, 6:46am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/2 "2021-09-20T06:46:30Z")

</div>

Don’t. These are intentionally unappealing and hard to use. Pointer programming is unsafe and will lead to crashes unless done very carefully. There is no need to use pointers in Julia unless you are interfacing with C libraries.

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [September 20, 2021, 7:07am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/4 "2021-09-20T07:07:52Z")

</div>

pointers **are** unsafe, but they are expressive  
for example, it’s hard to specify a node on a tree (structure like `Expr`) without pointers

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [September 20, 2021, 7:21am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/5 "2021-09-20T07:21:36Z")

</div>

Here’s a simple binary tree data structure:

```julia
mutable struct Tree{T}
    data :: T
    left :: Union{Tree{T}, Nothing}
    right :: Union{Tree{T}, Nothing}
end

Tree(x) = Tree{typeof(x)}(x, nothing, nothing)

```

Here it is in action:

```julia
julia> t = Tree("Hello")
Tree{String}("Hello", nothing, nothing)

julia> t.left = Tree("Left child")
Tree{String}("Left child", nothing, nothing)

julia> t.right = Tree("Right child")
Tree{String}("Right child", nothing, nothing)

julia> t
Tree{String}("Hello", Tree{String}("Left child", nothing, nothing), Tree{String}("Right child", nothing, nothing))

```

There are several real-world tree implementations in [DataStructures](https://juliacollections.github.io/DataStructures.jl/latest/). None of them use pointers.

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [September 20, 2021, 7:27am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/6 "2021-09-20T07:27:20Z")

</div>

I think you didn’t get my point. It is easy to build the structure.  
But what if you want to find (the l-l-l-r-r-l or sth )child and does operations.  
e.g.  
This is my simple code of building a simple filesystem using pointers.

```cpp
#include <iostream>
#include <map>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::getline;
using std::map;
using std::out_of_range;
using std::string;
using std::vector;
vector<string> split(string s,char spilter){
    vector<string>t;
    string temp;
    for(char i:s){
        if(i==spilter&&temp!=""){
            t.push_back(temp);
            temp="";
        }
        else{
            temp.push_back(i);
        }
    }
    if(temp!="")t.push_back(temp);
    return t;
}
enum FileSystemError{
    VOID_STR,
    UNFOUND,DIR_UNFOUND,FILE_UNFOUND,
    SAME_NAME_EXISTS,
    PROCESS_DENIED,
};

class File;
class Directory;
class FileSystem;

class File{
public:
    Directory *in;
    string filename;
    string contents;
    File(Directory*,string,string);
    File(File&);
    ~File();
};

class Directory
{
public:
    Directory *in;
    map<string,Directory*>dirs;
    map<string,File*>files;
    string dirname;
    Directory(Directory*,string);
    Directory(Directory&);
    ~Directory();

    bool hasdir(string);
    bool hasfile(string);
    bool has(string);
};
class FileSystem
{
public:
    Directory *root_dir;
    Directory *current_dir;
    FileSystem();
    ~FileSystem();
    Directory* getdir(Directory*,vector<string>);
    Directory* getdir(string);
    Directory* getdirin(string,string&);
    File* getfile(string);
    void ls_a(Directory*,unsigned);

    void ls(bool);
    void cd(string);
    void pwd();
    void mkdir(string);
    void rmdir(string);
    void cp(string,string);
    void rm(string);
    void mv(string,string);
    void touch(string,string);
    void cat(string);
};
File::File(Directory*p,string name,string con){
    in=p;filename=name;contents=con;
}
File::File(File&a){
    in=nullptr;
    filename=a.filename;
    contents=a.contents;
}
File::~File(){if(in!=nullptr){in->files.erase(filename);}}
Directory::Directory(Directory*place,string name){in=place;dirname=name;}
Directory::Directory(Directory&a){
    in=nullptr;
    dirname=a.dirname;
    for(auto i:a.dirs){
        Directory* p=i.second;
        dirs[i.first]=p;
        p->in=this;
    }
    for(auto i:a.files){
        File *p=i.second;
        files[i.first]=p;
        p->in=this;
    }
}
Directory::~Directory(){
    if(in!=nullptr)in->dirs.erase(dirname);
    for(auto i:dirs)delete i.second;
    for(auto i:files)delete i.second;
}
bool Directory::hasdir(string name){
    return dirs.find(name)!=dirs.end();
}
bool Directory::hasfile(string name){
    return files.find(name)!=files.end();
}
bool Directory::has(string name){
    return hasdir(name)||hasfile(name);
}
FileSystem::FileSystem(){
    root_dir=new Directory(nullptr,"");
    current_dir=root_dir;
}
FileSystem::~FileSystem(){delete root_dir;}
Directory *FileSystem::getdir(Directory*p,vector<string>path){
    for(auto i:path){
        if(i==".."){
            if(p!=nullptr)p=p->in;
        }
        else if(i!="."){
            if(!p->hasdir(i))throw DIR_UNFOUND;
            p=p->dirs[i];
        }
    }
    return p;
}
Directory *FileSystem::getdir(string path){
    if(path=="")throw VOID_STR;
    Directory* p=(path[0]=='/') ? root_dir : current_dir;
    return getdir(p,split(path,'/'));
}
Directory *FileSystem::getdirin(string path,string&back){
    if(path=="")throw VOID_STR;
    Directory* p=(path[0]=='/') ? root_dir : current_dir;
    auto d=split(path,'/');
    back=d.back();
    d.pop_back();
    return getdir(p,d);
}
File *FileSystem::getfile(string path){
    string name;
    auto p=getdirin(path,name);
    if(p->hasfile(name))return p->files[name];
    else throw FILE_UNFOUND;
}
void FileSystem::ls_a(Directory* pl,unsigned step){
    for(auto i:pl->dirs){
        for(unsigned i=0;i<step;++i)cout<<'\t';
        cout<<i.first<<"/\n";
        ls_a(i.second,step+1);
    }
    for(auto i:pl->files){
        for(unsigned i=0;i<step;++i)cout<<'\t';
        cout<<i.first<<"\n";
    }
}
void FileSystem::ls(bool _a){
    if(_a){
        ls_a(current_dir,0);
    }
    else{
        for(auto i:current_dir->dirs)cout<<i.first<<"/\n";
        for(auto i:current_dir->files)cout<<i.first<<"\n";
    }
}
void FileSystem::cd(string path){
    current_dir=getdir(path);
}
void FileSystem::pwd(){
    string s;
    Directory *temp=current_dir;
    while(temp!=root_dir){
        s=temp->dirname+"/"+s;
        temp=temp->in;
    }
    cout<<"/"+s<<'\n';
}
void FileSystem::mkdir(string path){
    string name;
    auto p=getdirin(path,name);
    p->dirs[name]=new Directory(p,name);
}
void FileSystem::rmdir(string path){
    auto p=getdir(path);
    auto q=current_dir;
    while(q!=nullptr){
        if(q==p)throw PROCESS_DENIED;
        q=current_dir->in;
    }
    delete p;
}
void FileSystem::cp(string from,string to){
    string name;
    auto p=getdirin(from,name);
    auto q=getdir(to);
    if(q->has(name))throw SAME_NAME_EXISTS;
    if(p->hasdir(name)){
        auto t=*(p->dirs[name]);
        q->dirs[name]=&t;
    }else if(p->hasfile(name)){
        auto t=*(p->files[name]);
        q->files[name]=&t;
    }
    else throw UNFOUND;
}
void FileSystem::rm(string path){
    string name;
    auto p=getdirin(path,name);
    if(p->hasdir(name)){
        delete p->dirs[name];
        p->dirs.erase(name);
    }
    else if(p->hasfile(name)){
        delete p->files[name];
        p->files.erase(name);
    }
    else throw UNFOUND;
}
void FileSystem::mv(string from,string to){
    string name;
    auto p=getdirin(from,name);
    auto q=getdir(to);
    if(p==q)return;
    if(q->has(name))throw SAME_NAME_EXISTS;
    if(p->hasdir(name)){
        auto t=*(p->dirs[name]);
        q->dirs[name]=&t;
        delete p->dirs[name];
        p->dirs.erase(name);
    }else if(p->hasfile(name)){
        auto t=*(p->files[name]);
        q->files[name]=&t;
        delete p->files[name];
        p->files.erase(name);
    }
    else throw UNFOUND;
}
void FileSystem::touch(string path,string contents=""){
    string name;
    auto p=getdirin(path,name);
    if(p->hasdir(name))throw SAME_NAME_EXISTS;
    else if(p->hasfile(name)){
        p->files[name]->contents=contents;
    }
    else{
        p->files[name]=new File(p,name,contents);
    }
}
void FileSystem::cat(string path){
    auto p=getfile(path);
    cout<<p->contents<<"\n";
}

```

without pointers, we can only use a list and will be quite slow

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [September 20, 2021, 7:32am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/7 "2021-09-20T07:32:47Z")

</div>

Everything you do with pointers in that code you can do with normal object references in Julia. Are you talking about emulating the `Directory` class? You would implement that as something like this:

```julia
mutable struct Directory
    in :: Directory
    dirs :: Dict{String, Directory}
    files :: Dict{String, File}
    dirname :: String
end

```

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [September 20, 2021, 7:35am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/8 "2021-09-20T07:35:07Z")

</div>

But how do you do this `Directory *current_dir;`?

By the way, I’m asking about how to use instead of why to use.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [September 20, 2021, 7:37am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/9 "2021-09-20T07:37:05Z")

</div>

```julia
current_dir = # some Directory object

```

You’ll have to be more specific about what you want to do in order for me to be more helpful…

The `FileSystem` type would be declared as:

```julia
mutable struct FileSystem
    root_dir :: Directory
    current_dir :: Directory
end

```

Those fields refer to `Directory` objects and work similar to pointers (except that you can’t segfault your program with them).

---

<div class="post-metadata">

**Author:** ![JonasIsensee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonasisensee/32/4704_2.png) [@JonasIsensee](https://discourse.julialang.org/u/JonasIsensee)\
**Post date:** [September 20, 2021, 7:37am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/10 "2021-09-20T07:37:33Z")

</div>

If you are worried about chaining the accesses to traverse the tree,  
you can just write: (Here without an actual tree and mathematical functions instead)

```julia
julia> left(x) = 2x
left (generic function with 1 method)

julia> right(x) = 2x+1
right (generic function with 1 method)

julia> ∘(left, left, right, left)(1)
20

```

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [September 20, 2021, 7:38am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/11 "2021-09-20T07:38:23Z")

</div>

I already know about that and that only works for binary trees.

for `(left, left, right, left)`, it will be slow if long.

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [September 20, 2021, 7:39am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/12 "2021-09-20T07:39:17Z")

</div>

The point is, current\_dir is **in** root\_dir! They are related!

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [September 20, 2021, 7:42am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/13 "2021-09-20T07:42:14Z")

</div>

Clearly I’m not getting it. What specific part of the code requires pointers? The C++ code is only using pointers to refer to objects, which is what a normal object reference does in Julia, except without the ability to segfault your program.

---

<div class="post-metadata">

**Author:** ![JonasIsensee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonasisensee/32/4704_2.png) [@JonasIsensee](https://discourse.julialang.org/u/JonasIsensee)\
**Post date:** [September 20, 2021, 7:43am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/14 "2021-09-20T07:43:16Z")

</div>

`mutable struct`s are heap allocated!

`dir = current_dir`

does not create a new object but refers to the exact same object!

```julia
julia> mutable struct A; x::Int; end

julia> a = A(42)
A(42)

julia> b = a
A(42)

julia> b.x = 43
43

julia> a
A(43)

```

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [September 20, 2021, 7:45am UTC](https://discourse.julialang.org/t/how-to-better-use-pointers/68433/15 "2021-09-20T07:45:33Z")

</div>

amusing  
~~How come I never realized it~~
