0

When initializing with a pointer a nullptr can be ambiguous if there are multiple constructors accepting a pointer argument.
You can solve this by casting C cast or static_cast, example:

#include <iostream>
#include <cstddef>

using namespace std;

struct A{
    A(int*){ cout << "int constructor" << endl;}
    A(double*) { cout << "double constructor" << endl;}
};

struct B{
    B(std::nullptr_t) { cout << "nullptr constructor" << endl;}
    B(int*){ cout << "int constructor" << endl;}
    B(double*) { cout << "double constructor" << endl;}
};

int main(){
    //A a(nullptr); constructor is ambiguous 
    A a1((int*)nullptr);// int constructor
    A a2(static_cast<double*>(nullptr));// double constructor

    B b(nullptr);// nullptr constructor
    return 0;
}

I included B to illustrate that a constructor with std::nullptr_t exist and is possible but for this question let's focus on A.

From "Why use static_cast(x) instead of (int)x?" I understand the most dangerous thing about C cast being you don't know which will be used:

The main reason is that classic C casts make no distinction between what we call static_cast<>(), reinterpret_cast<>(), const_cast<>(), and dynamic_cast<>(). These four things are completely different.

Are any of these casts unsafe for a nullptr or can you safely use the C-style cast?

2
  • 1
    Don't use the C-style cast. As explained in the question that you linked, you should always prefer the c++ cast versions over the C-style version. It also makes your code clearer, you are clearly stating what you are doing. Commented Nov 30, 2017 at 11:11
  • If you sometimes want to construct without a parameter, you could of course also have a default constructor A() and skip the nullptr. Commented Nov 30, 2017 at 13:46

2 Answers 2

2

A reinterpret cast is unsafe irrespective of what you're casting - the point is you're forcing the compiler to ignore it's own set of (very good) rules and trust your (usually wrong) intuition.

I consider dynamic_casting also somewhat hazardous since it allows you to compile down-casting and side-casting. Sometimes when just starting to work with this this can cause confusing NULL pointers appearing or run-time errors.

In your example it doesn't matter since the conversion is trivial, so you "can" use anything, but you probably shouldn't. The C-style case will probably be static since it's hard-coded in compilation time, so in your case it won't matter (but you can't be sure! it's not guaranteed!). This is more of a be safe convention - use static_cast since that's what you want to do, and that's the way to guarantee it. If your code becomes more advance/complex/difficult the "be safe" rule can really save you from nasty bugs.

In general, C++ should contain no native C, at least as a beginner, probably most of the time.

Sign up to request clarification or add additional context in comments.

8 Comments

Can but shouldn't is what I was looking for. I don't see how any of the casts can go wrong starting from a nullptr but I'll stay with safe casts.
The opinion on dynamic_cast is nonsense. The compiler ignores no rules, in fact it checks the validity and can throw or return null.
@MSalters While I realize down(side)-casting may be necessary at times, it's still not "safe" in the sense that can cause run-time errors/unexpected null values (think beginner perspective). I didn't think I should elaborate on my opinions, but if you feel it's nonsense what do you suggest? A lesser warning?
@MSalters Tried to do better by you, feel free to edit in.
@kabanus: FYI: reinterpret_casts are not a priori unsafe.
|
0

I feel that if the class allow multiple pointer types to construct then the class author should take design responsibility for explicit null pointers.

The default position is that null pointers are not handled, which is perfectly valid. The author can add a nullptr_t or no-args constructor if they want to handle explicit null pointers, but if not, the user should take it as a firm design warning.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.