I am reasonably familiar with the concept of smart pointers. But I struggle to get my head around how these would be used as members of a class/struct.
Question One:
Just for examples sake I have created a class which contains the member name and size of the char array holding the name:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
class A
{
unsigned int m_Size; char* m_Name;
public:
A(const char* name)
{
m_Size = strlen(name)+1;
m_Name = new char[m_Size];
memcpy(m_Name, name, m_Size);
std::cout << "Member name: " << m_Name << std::endl;
}
~A()
{
delete[] m_Name;
}
};
int main()
{
{
A a1("Jolene\0");
}
}
|
This program works as I would expect, but 'new' and 'delete' are explicitly called. I would prefer to use a smart pointer (if possible) instead, so that the memory management is automated to a certain extent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
class B
{
unsigned int m_Size; std::shared_ptr<char[]> m_Name;
public:
B(const char* name)
{
m_Size = strlen(name) + 1;
m_Name = std::make_shared<char[m_Size]>();
memcpy(m_Name, name, m_Size);
std::cout << "Member name: " << m_Name << std::endl;
}
~B()
{
std::cout << "Member name: " << m_Name << std::endl;
}
};
int main()
{
{
B b1("Jolene\0");
}
}
|
On the line:
m_Name = std::make_shared<char[m_Size]>();
I get two errors:
1). 'non-constant expression as array bound'
2). 'binary '='. no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)'
And on the line:
memcpy(m_Name, name, m_Size);
I get a further two errors:
1). 'no suitable conversion function from "std::shared_ptr<char[]>" to "void *" exists'
2). ' 'void * memcpy(void *,const void *,size_t)': cannot convert argument 1 from 'std::shared_ptr<char[]>' to 'void *'
Is it possible for this code to be corrected so that 'm_Name' is constructed as a char pointer via a smart pointer rather than by explicitly calling 'new' and 'delete' as in my first example?
Question Two:
In the end I managed to find a similar way of doing this that worked, but I had to use std::string rather than a char pointer in this example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
class C
{
std::unique_ptr<std::string> m_Name;
public:
C(std::string name)
: m_Name(std::make_unique<std::string>())
{
*m_Name = name;
std::cout << "Member name: " << *m_Name << std::endl;
}
~C()
{
std::cout << "Member name: " << *m_Name << std::endl;
}
};
int main()
{
{
C c1("Jolene\0");
}
}
|
'm_Name' is initialised successfully via the constructor, but in the destructor, I am still able to output 'm_Name', which surely means that it hasn't been automatically deleted by the smart pointer?
Am I right in thinking that 'm_Name' should be deleted automatically by the smart pointer and if so, where does this deletion take place?