Rick
Rick

Reputation: 7516

How does a pointer (built-in types) which gets constructed like a custom class work?

I've changed the question title and body see if it suits better :).


I read a member function signature on cppreference: unique_ptr/reset.

void reset( pointer ptr = pointer() ) noexcept;

and pointer is a member type of unique_ptr, documented as

pointer | std::remove_reference<Deleter>::type::pointer if that type exists, otherwise T*. Must satisfy NullablePointer

What I've learnt in the comments:

  1. pointer ptr = pointer() is somehow equivalent to e.g. int, using pointer = int*; pointer ptr = pointer()
  2. And if it's a built-in type like int, then ptr is a zero-initialized variable. I get a int* pointer with 0/NULL/nullptr here.
  3. There is not a "raw" statement for using pointer = int*; pointer ptr = pointer(), which is that int* ptr = int*() won't work.

I also read Do built-in types have default constructors? and that helps a lot.


I want to know a bit more about this behaviour(a built-in type can be constructed in a custom class way), if it can be explained in more details:

using pointer = int*; pointer ptr = pointer()

Seriously no "raw" syntax for this statment? I used to think that everything use a typedef or using could be written down with a "raw" version. Like a one-to-one mapping.

Upvotes: 3

Views: 146

Answers (1)

Rakete1111
Rakete1111

Reputation: 49028

There is no need for the "raw" syntax as you put it, since pointers can be zero initialized with a 0.

int *p = 0; // nullptr

I guess it might be useful for template argument deduction, but we already have a syntax for that: (int*)0. There isn't really a need to add yet more syntax for something small like that (or maybe someone forgot to add it; but either way, it's unnecessary now).

The T(...) syntax is mostly used to initialize objects of user-defined types.

I used to think that everything use a typedef or using could be written down with a "raw" version.

Here's another example:

int a;
a.~int(); // syntax error

using Int = int;
a.~Int(); // ok!

The first statement is disallowed because it's a no-op. The second isn't because in a generic context it might do something (destroy the object) instead of being a no-op. Since the language doesn't want to unnecessarily restrict this going through an alias is allowed.

It's for this same reason that pointer() is allowed even if you can't write out the syntax: If it would be disallowed it would be a pain to work in a generic context.

Upvotes: 2

Related Questions