\$\begingroup\$
\$\endgroup\$
1
Relatively new to C++, not sure if I'm doing everything right, any advice would be appreciated. The site does not allow me to post this question with that little actual text, so I am artificially extending it with this dummy text. Here's what I wrote:
#include <iostream>
template<typename T>
class DefaultPointer {
const T* value_pointer;
const T default_value;
public:
DefaultPointer(const T* ptr, const T& def) : value_pointer(ptr), default_value(def) {
}
const T get() {
if (value_pointer == nullptr) {
return default_value;
}
return *value_pointer;
}
};
template<typename T>
class Default {
const T value;
const T default_value;
public:
Default(const T& value, const T& def) : value(value), default_value(def) {
}
const T get() {
if (!(bool)value) {
return default_value;
}
return value;
}
};
int main() {
const int test_value = 1;
const int* const pointer = &test_value;
std::cout << DefaultPointer<int>(pointer, 0).get();
}
1 Answer 1
\$\begingroup\$
\$\endgroup\$
2
Here are some considerations:
Use of
const
:- In your
DefaultPointer
andDefault
classes, theget
method does not modify any member variables, so it's good practice to mark it asconst
to indicate that calling this method won't change the object's state. - For the member variables
value_pointer
andvalue
, consider if you really want them to beconst
. This makes your objects immutable after they're constructed, which might be your intention. If you ever need to change the pointer or value after construction, you'll need to remove theconst
.
- In your
Checking for null pointers and zero values:
- In
Default
, you checkif (!(bool)value)
. This works for numeric types where0
is implicitly convertible tofalse
, but it might not be clear or applicable for all types T. Consider if there's a more explicit or type-safe way to handle this, depending on what types you expectT
to be.
- In
Return Type Optimization:
- Returning by
const T
is unusual. Typically, you'd return by value (T
) or byconst T&
if you're returning a reference to an existing object (to avoid copying). Returning byconst T
prevents the caller from modifying the returned value, which is unnecessary for built-in types and might inhibit move semantics for user-defined types.
- Returning by
Error Handling:
- Consider what should happen if an invalid pointer is passed to
DefaultPointer
. Your current implementation gracefully handlesnullptr
, but what about dangling or uninitialized pointers? This might be beyond the scope of your current practice but is worth thinking about as you advance.
- Consider what should happen if an invalid pointer is passed to
Usage Example:
- Your
main
function demonstrates usage ofDefaultPointer
but notDefault
. It might be beneficial to include an example of howDefault
is intended to be used, especially considering its reliance on the boolean conversion ofT
.
- Your
Other practices to keep in mind:
- If you're using C++11 or newer, you can use
nullptr
instead ofNULL
for null pointer constants. It's more type-safe and clear. - Consider using smart pointers (
std::unique_ptr
,std::shared_ptr
) if you plan to work with dynamically allocated memory. They help manage memory more safely and automatically.
- If you're using C++11 or newer, you can use
answered Jan 25, 2024 at 5:14
-
\$\begingroup\$ I do actually expect the parameter of Default to have a
bool
operator. I now have a question: how do I check for a dangling or an uninitialized pointer? And is there a way that is considered a good practice for such a check? \$\endgroup\$YurichBRO– YurichBRO2024年01月25日 06:30:45 +00:00Commented Jan 25, 2024 at 6:30 -
\$\begingroup\$ There isn't a fullproof method to checking or I don't think there is \$\endgroup\$37307554– 373075542024年01月25日 06:37:22 +00:00Commented Jan 25, 2024 at 6:37
lang-cpp
get()
is not very idiomatic c++. Preferoperator *()
. \$\endgroup\$