I have seen a great answer here which has helped me to a great extent (Proper way to create unique_ptr that holds an allocated array) but I still have an issue.
Code:
void CSelectedBroHighlight::BuildSelectedArray()
{
CString strText;
// empty current array
m_aryStrSelectedBro.RemoveAll();
// get selected count
const auto iSize = m_lbBrothers.GetSelCount();
if(iSize > 0)
{
//auto pIndex = std::make_unique<int[]>(iSize);
auto pIndex = new int[iSize];
m_lbBrothers.GetSelItems(iSize, pIndex);
for(auto i = 0; i < iSize; i++)
{
m_lbBrothers.GetText(pIndex[i], strText);
m_aryStrSelectedBro.Add(strText);
}
delete[] pIndex;
}
}
If I turn pIndex
into a smart pointer:
auto pIndex = std::make_unique<int[]>(iSize);
So that I don't need the delete[] pIndex;
call. Then I can't pass pIndex
to GetSelItems
. I can pass pIndex.release()
here but then we have a problem for deleting again.
auto pIndex = std::make_unique<int[]>(iSize).release();
then I can pass it, but now have the issue of calling delete[] pIndex;
.Whats correct?
If you need access to the pointer to an object managed by a std::unique_ptr
without transferring ownership, you can call its get()
method. This is useful for interop with a C interface such as here (GetSelItems()
is really just wrapping a call to SendMessage
with the LB_GETSELITEMS
message).
That'd work, though in this case I'd probably use a std::vector<int>
instead. It provides the same properties as a std::unique_ptr
with respect to automatic cleanup, but also has other features that come in handy (specifically range adapters). It also feels more natural to use a container here, but that's a matter of personal preference.
The following implements the proposed changes:
void CSelectedBroHighlight::BuildSelectedArray() {
// empty current array
m_aryStrSelectedBro.RemoveAll();
// get selected count
auto const sel_item_count{ m_lbBrothers.GetSelCount() };
if(sel_item_count > 0) {
// get selected indices
std::vector<int> sel_items(sel_item_count);
m_lbBrothers.GetSelItems(sel_items.size(), sel_items.data());
// iterate over all selected item indices
for(auto const index : sel_items) {
CString strText;
m_lbBrothers.GetText(index, strText);
m_aryStrSelectedBro.Add(strText);
}
}
}
This provides the same automatic cleanup as an implementation based on std::unique_ptr
, but also enables use of a range-based for
loop further down.