This might be a very basic question, but I tried to find the answer in SO and couldn't find the exact answer to it.
What's the point of initializing a const
pointer with nullptr
?
int *const pi = nullptr;
Why does the compiler not emit a warning or error, seeing how pointer pi
can't be used effectively anywhere in the program?
I have tried compiling this with g++ -w
.
Also, Can you give some use case where a const
pointer will get initialized to nullptr
for a valid purpose in real code?
Do not confuse const
, which means: "The values cannot change after initialization" with "this value is always, under all circumstances a nullptr
". What I mean is this:
struct foo {
int *const pi = nullptr;
foo( int* p) : pi(p) {}
};
Different instances of foo
can have different values for pi
.
Another way to have the initialization conditional is:
int *const pi = (some_condition) ? nullptr : some_pointer;
Even with a plain
int *const pi = nullptr;
there is nothing wrong. It is basically giving a different name to nullptr
, so you can use pi
anywhere where you can use a nullptr
. For example as sentinel in a container:
int * const empty = nullptr;
for ( int* element : container) {
if (element != empty) do_something(element);
}
This might be considered obfuscation, and directly using nullptr
would be more readable. Though consider the sentinel value changes later on, then using empty
makes is simple to replace all occurences of it.
Although I agree that initializing a const
pointer to nullptr
isn't generally especially useful, one situation where it may me appropriate is where you would conditionally define the const pi
pointer to either nullptr
or some other (valid) address, depending on a compile-time setting, like in the following example. (The const
qualifier prevents other code from inadvertently changing the value and, thusly, breaking the aforementioned compile-time condition.)
#include<iostream>
#define USENULL 1 // Comment out this line to get a 'valid' pointer!
int main()
{
int a = 42;
#ifdef USENULL
int* const pi = nullptr;
#else
int* const pi = &a;
#endif
int* pa = pi;
if (pa) std::cout << *pa;
else std::cout << "null pointer";
std::cout << std::endl;
return 0;
}
Such a situation could arise when you need to differentiate between debug and release builds, for example.
I'll try to generalize @AdrianMole's (second) example:
Sometimes, a piece of code is a degenerate case or an outlier case of a more general instruction or pattern. Thus:
In @AdrianMole's example, there is an out-of-source parameter which controls whether pi
should have a meaningful value or not. You don't want to twist your source up too much in order to accommodate this scenario, so you keep the same code but use nullptr
, likely with a later (run-time) check for whether you have a nullptr
or not.
You might have a template class where the general definition is something like:
template <typename T> class A { int *const pi = whatever<T>(); }
with a specialization
template <> class A<foo_t> { int *const pi = nullptr; }
because you want to avoid calling whatever<foo>()
.
It is likely that such code can be improved to avoid the explicit nullptr
assignment. But it would be a bit excessive to push developers into doing this through a warning.
(An error is out of the question since it's perfectly valid code in terms of the language standard.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.