Simpler method to insert a value into a potentially null pointer

Viewed 94

I have a pointer which I wish to point to an LRESULT which I am returning from a function. Currently, to insert the value returned from the function, I am storing it in a temporary variable then making the pointer point to that variable. I want to know if there is a way of doing this without the temporary variable.

Coded example follows:

LRESULT* ret = nullptr;
//---
LRESULT temp = foo();
ret = &temp;
//---
return ret == nullptr ? bar() : *ret;

I have tried using this:

*ret = foo();

But this does not work, as ret is a null pointer and has no assigned memory to put the value in.

I have also tried this:

ret = &(foo());

But this does not work as well.

edit:

for context the full function I am working on is as follows:

LRESULT CALLBACK Window::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)  noexcept
{
    LRESULT* ret = nullptr;
    if (msg == WM_NCCREATE)
    {
        const CREATESTRUCTW* const pCreate = reinterpret_cast<CREATESTRUCTW*>(lParam);
        Window* const pWnd = static_cast<Window*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pWnd));
        SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Window::HandleMsgThunk));
        LRESULT lr = pWnd->HandleMsg(hWnd, msg, wParam, lParam);
        ret = &lr;
    }
    return ret == nullptr ? DefWindowProc(hWnd, msg, wParam, lParam) : *ret;
}

and to once more reiterate, the function works fine in its current state, I merely wish to remove the seemingly unessecery variable lr

2 Answers

I think you can do something like this then you can remove both ret and lr variables.

LRESULT CALLBACK Window::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)  noexcept
{
    if (msg == WM_NCCREATE)
    {
        const CREATESTRUCTW* const pCreate = reinterpret_cast<CREATESTRUCTW*>(lParam);
        Window* const pWnd = static_cast<Window*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pWnd));
        SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Window::HandleMsgThunk));
        return pWnd->HandleMsg(hWnd, msg, wParam, lParam);
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

To use a pointer, it must point to something valid, or else be null. Anything else leads to undesirable results.

The code you have shown has undefined behavior, as you are accessing the memory for lr outside of its scope, after its lifetime has ended. The only reason your code seems to "work" is because that memory hasn't been overwritten yet when you dereference the pointer.

To solve that, you would have to move the declaration of lr outside of the if block:

LRESULT CALLBACK Window::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)  noexcept
{
    LRESULT* ret = nullptr;
    LRESULT lr; // <-- MOVED HERE!
    if (msg == WM_NCCREATE)
    {
        const CREATESTRUCTW* const pCreate = reinterpret_cast<CREATESTRUCTW*>(lParam);
        Window* const pWnd = static_cast<Window*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pWnd));
        SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Window::HandleMsgThunk));
        lr = pWnd->HandleMsg(hWnd, msg, wParam, lParam);
        ret = &lr;
    }
    return ret == nullptr ? DefWindowProc(hWnd, msg, wParam, lParam) : *ret;
}

Alternatively, you can use std::optional (C++17 and later only) instead of a raw pointer, that will save you from having to declare a separate variable for it to refer to:

#include <optional>

LRESULT CALLBACK Window::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)  noexcept
{
    std::optional<LRESULT> ret;
    if (msg == WM_NCCREATE)
    {
        const CREATESTRUCTW* const pCreate = reinterpret_cast<CREATESTRUCTW*>(lParam);
        Window* const pWnd = static_cast<Window*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pWnd));
        SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Window::HandleMsgThunk));
        ret = pWnd->HandleMsg(hWnd, msg, wParam, lParam);
    }
    return !ret.has_value() ? DefWindowProc(hWnd, msg, wParam, lParam) : ret.value();
}

However, the simplest solution would be to just eliminate the LRESULT variables altogether, as you don't actually need them:

LRESULT CALLBACK Window::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept
{
    if (msg == WM_NCCREATE)
    {
        const CREATESTRUCTW* const pCreate = reinterpret_cast<CREATESTRUCTW*>(lParam);
        Window* const pWnd = static_cast<Window*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pWnd));
        SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Window::HandleMsgThunk));
        return pWnd->HandleMsg(hWnd, msg, wParam, lParam);
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}
Related