A language with pointers also allows a function to alter its
logical (not syntactical) argument values in a way that negatively affects the caller.
There isn't much practical difference between using
// void c_func_alters_deref_pfoo(Foo * pfoo)
Foo foo = { ... };
c_func_alters_deref_pfoo(&foo);
and
// void cpp_func_alters_foo(Foo & foo)
Foo foo = { ... };
cpp_func_alters_foo(foo);
besides the ability to pass null or otherwise invalid pointers in the C-style version, which can (depending on situation) either simplify your API or be a source of bugs.