I have an assignment where I have to use a linked list of node with void* as the data. I would be filling the nodes with an object. I want to know some way of accessing the members of the object after it is in the linked list, other than casting it to the class. Is it possible? Also, here's a chunk of my code just in case it helps clarify my question.
struct Node
{
void* data_;
Node* next_;
Node()
{
data_ = 0;
next_ = 0;
}
};
class Star
{
private:
char name_[ENTRY_SZ];
long temperature_;
double luminosity_;
double mass_;
double radius_;
public:
static char filePath_[ENTRY_SZ];
Star(char* name);
void SetTemperature(char* temp);
void SetLuminosity(char* lum);
void SetMass(char* mass);
void SetRadius(char* rad);
void PrintToConsole();
void AppendToFile();
};
I want to be able to call the PrintToConsole function after it is in a void*.
You cannot work with the pointee of a void* without first casting it first. If it points at a Star, for example, you could do something like this:
static_cast<Star*>(data_)->PrintToConsole(); // Haha, Star star!
That said, in C++, it's pretty unusual to store things like this. You're much better off using a template class so that you get back the type information you need.
No. You have to cast it to the appropriate object.
I would question the reason on using void pointers.
I would also suggest a dynamic cast might be better
You should cast it to the class. But if you really don't want to, you can use the offsetof macro:
The macro offsetof expands to a constant of type std::size_t, the
value of which is the offset, in bytes, from the beginning of an
object of specified type to its specified member, including padding if
any.
If type is not a standard layout type, the behavior is undefined.
If member is a static member or a member function, the behavior is
undefined.
But you should just cast it to the class.
EDIT: Ah, I see you want to access a method of the class. That's not possible. You should cast it to the class.
Since this is an assignment, you might be best to ask your teacher/mentor as to what their intents are for using a void* type in C++; void* types are not inherently bad, but there other ways of achieving similar results while maintaining language consistency.
To answer directly:
I want to know some way of accessing the members of the object after it is in the linked list, other than casting it to the class. Is it possible?
Yes it is possible, but not using the void* idiom. Using your code as an example, you would indeed have to cast to the appropriate type and be certain the types pointed to are compatible if you keep the void*, example:
struct Node
{
void* data_;
Node* next_;
Node()
{
data_ = 0;
next_ = 0;
}
};
class Star
{
public:
void PrintToConsole() {} // empty to avoid not-defined errors
};
int main() {
Node n;
n.data_ = new int(42);
static_cast<Star*>(n.data_)->PrintToConsole(); // this will compile fine, but what happens here is undefined
delete static_cast<int*>(n.data_); // can't delete void*, have to cast
return 0;
}
Again, since this is an assignment, your professor is probably just trying to teach about pointers and casting or the type system and you probably haven't learned about C++ templates, but since you asked, here's your code using templates:
template < typename T >
struct Node
{
T data_;
Node* next_;
// use member init list to construct default T object
Node() : data_(), next_(0)
{
}
};
class Star
{
public:
void PrintToConsole() {} // empty to avoid not-defined errors
};
int main() {
Node<Star*> n;
n.data_ = new Star();
n.data_->PrintToConsole(); // OK
delete n.data_; // no cast needed since data_ is a Star* type
Node<int*> n2;
n2.data_ = new Star(); // compiler error (data_ is of type int* not Star*)
n2.data_->PrintToConsole(); // compiler error (int has no member named PrintToConsole)
delete n.data_;
return 0;
}
This is just a simple example to illustrate what you were asking and it's still probably best to ask your teacher for more clarification if your confused on the topic.
Hope that can help.
Related
I want to find a way to encapsulate a header-only 3rd party library without exposing its header files. In our other projects, we encapsulate by using void*: in the implementation, we allocate memory and assign to it, and cast to pointer of its original type when we use it. But this time, the encapsulated class is used frequently, hence dynamic allocation is unacceptable. Here is another solution I'm currently considering.
Assuming that the encapsulated class need N bytes, I will make a char array member variable of size N in the wrapper class, named data, for instance. In the implementation, when I try to assign an object of the encapsulated class to the wrapper, or forward a function call, I need to cast &data to the pointer of encapsulated class by reinterpret_cast, firstly. The char array is completely a placeholder. To make this clear, here is a sample code.
#include <iostream>
struct Inner {
void print() const {
std::cout << "Inner::print()\n";
}
};
struct Wrapper;
Inner* addressof(Wrapper&);
const Inner* addressof(const Wrapper&);
struct Wrapper {
Wrapper() {
Inner* ptr = addressof(*this);
*ptr = Inner();
}
void run() const {
addressof(*this)->print();
}
char data[1];
};
Inner* addressof(Wrapper& w) {
return reinterpret_cast<Inner*>(&(w.data));
}
const Inner* addressof(const Wrapper& w) {
return reinterpret_cast<const Inner*>(&(w.data));
}
int main() {
Wrapper wrp;
wrp.run();
}
From the view of memory, this seems make sense. But I'm sure if this is some kind of undefined behaviour.
Additionally, I want to know if there is a list of undefined behaviour. Seems like cppreference doesn't contain such thing and C++ standard specfication is really hard to understand.
What you have here is undefined behavior. The reason is when you reinterpret an object to a different type, you are not allowed to modify it until you cast it back to the original type.
In your code, you originally have the data as a char[1]. Later, in your constructor, you reinterpret_cast &data as Inner*. At this point, modifying the its value will produce undefined behavior.
What you could do however, is to first create a Inner object, then cast it and store it in the char[1]. Later you can cast the char[1] back to the Inner object and do anything with the Inner object as wanted.
So now your constructor would look like this:
Wrapper() {
Inner inner;
char* ptr = reinterpret_cast<char*>(&inner);
std::memcpy(data, ptr, 1);
}
However, if you did it like this, then you don't even need the reinterpret_cast there as you can directly memcpy from inner:
Wrapper() {
Inner inner;
std::memcpy(data, &inner, 1);
}
Better, if you have C++20, then you can and should use std::bit_cast, along with std::byte(C++17) and std::array(C++11):
struct Wrapper {
Wrapper()
: data(std::bit_cast<decltype(data)>(Inner{}))
{}
void run() const {
std::bit_cast<Inner>(data).print();
}
std::array<std::byte, 1> data;
};
Demo: https://godbolt.org/z/MaT5sasaT
Let's say I want to represent a binary tree in C++. Usually, I want a Node struct like this:
struct Node {
Node* left
Node* right;
};
(Here I use struct and raw pointers just for simplicity. I know I should use smart pointers for memory management.)
This representation has a problem: I can never have a deep-const tree. (Correct me if I can.) I may mark a single Node const, but its children is hard-coded as non-const in the Node struct.
(I may use some template hack to make left and right optionally const, but this makes the const Node and non-const Node incompatible.)
Soon I found out, if I magically had some deep-const pointer (say deep_const_pointer, which makes constness transitive), I can use that pointer in Node so that having a const node automatically means having a const sub-tree.
I tried to write a deep-const pointer class, and here is what I end up with:
template <typename T>
class deep_const_pointer {
public:
explicit deep_const_pointer(const T* p_)
: p{const_cast<T*>(p_)} {}
const T& operator*() const { return *p; }
T& operator*() { return *p; }
const T* operator->() const { return p; }
T* operator->() { return p; }
// etc.
private:
T* p;
};
Here I cast out the const in the constructor and optionally add it back according to the constness of this pointer-like object. However, this implementation allows the following:
const int i = 42;
deep_const_pointer<int> p{&i};
*p = 0; // Oops!
So it depends on the user to correctly mark whether the pointer is const or not.
How should I build a deep-const pointer class? Ideally, I want the const check happen at compile-time, and that pointer class takes as much memory as a raw pointer. (Which rules out the solution to save the constness to a bool member variable and check on each access.)
EDIT: I checked std::experimental::propagate_const, and it is indeed not a "deep-const" pointer from my perspective. What I meant by deep-const pointer P is:
Constant P is pointer-to-const;
Mutable P is pointer-to-mutable;
A const reference to a non-const P is treated as if it were a const P;
Since pointer-to-const has value semantics, a const P should be trivially copyable.
propagate_const fails to match the requirement because:
It never accepts a pointer-to-const;
It is not copyable (copy constructors explicitly deleted);
From the comments and answer I received, I guess such a P is not implementable in C++.
Writing a transitive-const smart pointer is a solved problem, just look up std::experimental::propagate_const<>. It shouldn't be too hard to find appropriate implementations.
In your own try, you got constructing from a raw pointer wrong. You should not add const to the pointee-type, nor strip it out with a cast.
Fixed:
explicit deep_const_pointer(T* p_)
: p{p_} {}
I am implementing standart template tree structure, and I came across small problem.
Idea that each node will hold pointer to some data. Later in order to delete element correctly I need to know if its a single pointer or pointer to an array.
Inside of my tree->ReleaseMemory() method I have this code:
if (node->_data != NULL) {
switch (_destructionMethod){
case tree_delete:
delete node->_data; break;
case tree_deleteList:
delete [] node->_data; break;
case tree_free:
free(node->_data); break;
}
}
where _destructionMethod has been set during initialisation of the node.
Is there any way I can choose correct destructor without predefining it in special variable for it during initialisation ?
Thanks!
First basic:
delete is used when you allocate memory with new:
int *p = new int;
int *a = new int[10];
//...
delete p;
delete []a; //note the difference!
free is used when you allocate memory with malloc:
int *p = (int*)malloc(sizeof(int) * 1);
int *a = (int*)malloc(sizeof(int) * 10);
//...
free(p);
free(a); //no difference!
Now your problem:
Is there any way I can choose correct destructor without predefining it in special variable for it during initialisation
Consider policy-based design. That means, write allocator that will encapsulate allocation and deallocation in a class and use that consistently in your code.
No, there is no portable way to find out what allocator a particular pointer originally came from.
There's no way to interrogate a pointer to find out how it was allocated, but a common idiom is to give the allocated object itself responsibility for its own destruction. It looks like your object types are not all class types, though, so you would need to wrap them in order to do this. For example:
class destroyable_node
{
virtual void destroy() = 0;
};
template <typename T> class object_node : public destroyable_node
{
private:
T * value_;
public:
// Presumes T is copy-constructable.
object_node(T value) : value_( new T(value) ) {}
operator T&() {return value_;}
operator T const &() const {return value_;}
void destroy() {delete value_;}
};
template<typename T> class array_node : public destroyable_node
{
private:
T * value_;
public:
array_node(T[] value)
: value_( new T[ sizeof(value)/sizeof(T) ] )
{
std::copy(value, value + sizeof(value)/sizeof(T), value_);
}
operator T*() {return value_;}
operator T const *() const {return value_;}
void destroy() {delete[] value_;}
};
...and so on.
Don't do this at all. Use a smart pointer, like shared_ptr from C++0x or Boost or if that is not an option, auto_ptr from C++. If you could have more than one object, consider using std::vector.
Manual resource management is messy and difficult to get right.
Maybe a better design is to implement an abstract interface used by your container with three concrete subclasses that know what kind of thing they hold pointers to. Your container would simply call a destroy() method in the base class and let the derived classes worry about calling the correct destructor.
I'm in the process of writing a smart pointer countedptr and I've hit a speed bump. The basic function of countedptr is to work like any other smart pointer and also have a count of how many pointers are pointing to a single object. So far, the code is:
[SOLVED]
#include "std_lib_facilities.h"
template <class T>
class counted_ptr{
private:
T* pointer;
int* count;
public:
counted_ptr(T* p = 0, int* c = new int(1)) : pointer(p), count(c) {} // default constructor
explicit counted_ptr(const counted_ptr& p) : pointer(p.pointer), count(p.count) { ++*count; } // copy constructor
~counted_ptr() { --*count; delete pointer; }
counted_ptr& operator=(const counted_ptr& p)
{
pointer = p.pointer;
count = p.count;
++*count;
return *this;
}
T* operator->() const{ return pointer; }
T& operator*() const { return *pointer; }
int Get_count() const { return *count; }
};
int main()
{
counted_ptr<double> one;
counted_ptr<double>two(one);
int a = one.Get_count();
cout << a << endl;
}
When I try to do something like
one->pointer = new double(5);
then I get a compiler error saying "request for member 'pointer' in '*(&one)->counted_ptr::operator->with T = double' which is of non-class type double".
I considered making a function to do this, and while I could make a function to allocate an array of T's, I can't think of a way of making one for allocating actual objects. Any help is appreciated, thanks.
Old Solution
What about another assignment operator?
counted_ptr& counted_ptr::operator=(T* p)
{
if (! --*count) { delete count; }
pointer = p;
count = new int(1);
return *this;
}
...
one = new double(5);
Also, your destructor always deletes a shared pointer, which is probably what caused *one to be a random nomber. Perhaps you want something like:
counted_ptr::~counted_ptr() { if (! --*count) { delete pointer; delete count; } }
New Solution
As you want repointing a counted_ptr (eg one = new double(5)) to update all related counted_ptrs, place both the pointer and the count in a helper class, and have your pointer class hold a pointer to the helper class (you might already be headed down this path). You could go two ways in filling out this design:
Make the helper class a simple struct (and a private inner class) and place all the logic in the outer class methods
Make counted_ptr the helper class. counted_ptr maintains a reference count but doesn't automatically update the count; it's not a smart pointer, it only responds to release and retain messages. If you're at all familiar with Objective-C, this is basically its traditional memory management (autoreleasing aside). counted_ptr may or may not delete itself when the reference count reaches 0 (another potential difference from Obj-C). counted_ptrs shouldn't be copyable. The intent is that for any plain pointer, there should be at most one counted_ptr.
Create a smart_ptr class that has a pointer to a counted_ptr, which is shared among smart_ptr instances that are supposed to hold the same plain pointer. smart_ptr is responsible for automatically updating the count by sending its counted_ptr release and retain methods.
counted_ptr may or may not be a private inner class of shared_ptr.
Here's an interface for option two. Since you're doing this as an exercise, I'll let you fill out the method definitions. Potential implementations would be similar to what's already been posted except that you don't need a copy constructor and copy assignment operator for counted_ptr, counted_ptr::~counted_ptr doesn't call counted_ptr::release (that's smart_ptr::~smart_ptr's job) and counted_ptr::release might not free counted_ptr::_pointer (you might leave that up to the destructor).
// counted_ptr owns its pointer an will free it when appropriate.
template <typename T>
class counted_ptr {
private:
T *_pointer;
size_t _count;
// Make copying illegal
explicit counted_ptr(const counted_ptr&);
counted_ptr& operator=(const counted_ptr<T>& p);
public:
counted_ptr(T* p=0, size_t c=1);
~counted_ptr();
void retain(); // increase reference count.
bool release(); // decrease reference count. Return true iff count is 0
void reassign(T *p); // point to something else.
size_t count() const;
counted_ptr& operator=(T* p);
T& operator*() const;
T* operator->() const;
};
template <typename T>
class smart_ptr {
private:
counted_ptr<T> *_shared;
void release(); // release the shared pointer
void retain(); // retain the shared pointer
public:
smart_ptr(T* p=0, int c=1); // make a smart_ptr that points to p
explicit smart_ptr(counted_ptr<T>& p); // make a smart_ptr that shares p
explicit smart_ptr(smart_ptr& p); // copy constructor
~smart_ptr();
// note: a smart_ptr's brethren are the smart_ptrs that share a counted_ptr.
smart_ptr& operator=(smart_ptr& p); /* Join p's brethren. Doesn't alter pre-call
* brethren. p is non-const because this->_shared can't be const. */
smart_ptr& operator=(counted_ptr<T>& p); /* Share p. Doesn't alter brethren.
* p is non-const because *this isn't const. */
smart_ptr& operator=(T* p); // repoint this pointer. Alters brethren
size_t count() const; // reference count
T& operator*() const; // delegate these to _shared
T* operator->() const;
};
Hopefully, the only ambiguous points above are the intentional ones.
(Sorry, newbie here, and can't leave comments). What Adatapost added, "one=new double(5);" should work. One other change needed, though: the reference counting needs a little help.
...
~counted_ptr() {
--*count;
// deallocate objects whose last reference is gone.
if (!*count)
{
delete pointer;
delete count;
}
}
counted_ptr& operator=(const counted_ptr& p)
{
// be careful to accommodate self assignment
++*p.count;
// may lose a reference here
--*count;
if (!*count)
{
delete pointer;
delete count;
}
count=p.count;
pointer=p.pointer;
return *this;
}
Of course, there's some code repetition here. It might make sense to refactor that code into its own function, e.g.
private:
/** remove our reference */
void release()
{
--*count;
if (!*count)
{
delete pointer;
delete count;
}
}
Did you, perhaps, mean "one.pointer=new double(5);"? Writing "one->pointer=new double(5);" invokes counted_ptr<double>::operator->. That is, it is approximately equivalent to:
double *tmp = one.operator->(); // returns one.pointer
tmp->pointer = new double(5);
But a double pointer isn't a structure, and so it doesn't have a pointer member.
Since the immediate problem has already been solved, I want to offer something more long term:
As you continue to develop this code, you'll definitely want to offer it up for full review by experienced programmers, whether here or elsewhere. There were a few obvious problems with your code as you posted it, though outis has helped correct them. But even once your code all compiles and seems to work in your own tests, there may be tests and situations which you haven't yet learned to think about. Smart pointers can easily have subtle problems that don't show up until very specific situations. So you'll want others to look over your code to find anything which you may have missed.
Please don't take this as any kind of insult towards your current code. I'm just offering this as friendly advice to ensure you learn the most you can out of this project.
Unless you are not doing this for academic reasons, you might want to use consider using the use_count() member of boost::shared_ptr. It's not entirely efficient, but it does work and you're better off using something well tested, mature, and thread safe. If you are doing this for learning purposes, be sure to check out the treatment of Reference Counting and Smart Pointers in More Effective C++.
You need to decrement the count and possibly delete the pointer to the old value in operator = before you overwrite it. You also need 'delete count' everywhere you have 'delete pointer' to avoid leaking memory
I have a class to parse a matrix that keeps the result in an array member:
class Parser
{
...
double matrix_[4][4];
};
The user of this class needs to call an API function (as in, a function I have no control over, so I can't just change its interface to make things work more easily) that looks like this:
void api_func(const double matrix[4][4]);
The only way I have come up with for the caller to pass the array result to the function is by making the member public:
void myfunc()
{
Parser parser;
...
api_func(parser.matrix_);
}
Is this the only way to do things? I'm astounded by how inflexible multidimensional arrays declared like this are. I thought matrix_ would essentially be the same as a double** and I could cast (safely) between the two. As it turns out, I can't even find an unsafe way to cast between the things. Say I add an accessor to the Parser class:
void* Parser::getMatrix()
{
return (void*)matrix_;
}
This will compile, but I can't use it, because there doesn't seem to be a way to cast back to the weirdo array type:
// A smorgasbord of syntax errors...
api_func((double[][])parser.getMatrix());
api_func((double[4][4])parser.getMatrix());
api_func((double**)parser.getMatrix()); // cast works but it's to the wrong type
The error is:
error C2440: 'type cast' : cannot convert from 'void *' to 'const double [4][4]'
...with an intriguing addendum:
There are no conversions to array types, although there are conversions to references or pointers to arrays
I can't determine how to cast to a reference or pointer to array either, albeit that it probably won't help me here.
To be sure, at this point the matter is purely academic, as the void* casts are hardly cleaner than a single class member left public!
Here's a nice, clean way:
class Parser
{
public:
typedef double matrix[4][4];
// ...
const matrix& getMatrix() const
{
return matrix_;
}
// ...
private:
matrix matrix_;
};
Now you're working with a descriptive type name rather than an array, but since it's a typedef the compiler will still allow passing it to the unchangeable API function that takes the base type.
Try this. It compiles cleanly on gcc 4.1.3:
typedef double FourSquare[4][4];
class Parser
{
private:
double matrix_[4][4];
public:
Parser()
{
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
matrix_[i][j] = i*j;
}
public:
const FourSquare& GetMatrix()
{
return matrix_;
}
};
void api_func( const double matrix[4][4] )
{
}
int main( int argc, char** argv )
{
Parser parser;
api_func( parser.GetMatrix() );
return 0;
}
I've used a union like this to pass around matrices in the past:
union matrix {
double dflat[16];
double dmatr[4][4];
};
Then pass a pointer in to your setter and copy the data into the matrix in your class.
There are ways of handling this otherwise (that are more generic), but this solution tends to be the cleanest in the end, in my experience.
I thought matrix_ would essentially be the same as a double**
In C there are true multi-dimensional arrays, not arrays of pointers to arrays, so a double[4][4] is a contiguous array of four double[4] arrays, equivalent to a double[16], not a (double*)[4].
There are no conversions to array types, although there are conversions to references or pointers to arrays
Casting a value to a double[4][4] would attempt to construct one on the stack - equivalent to std::string(parser.getMatrix()) - except that the array doesn't supply a suitable constructor. You probably did't want to do that, even if you could.
Since the type encodes the stride, you need a full type (double[][] won't do). You can reinterpret cast the void* to ((double[4][4])*), and then take the reference. But it's easiest to typedef the matrix and return a reference of the correct type in the first place:
typedef double matrix_t[4][4];
class Parser
{
double matrix_[4][4];
public:
void* get_matrix () { return static_cast<void*>(matrix_); }
const matrix_t& get_matrix_ref () const { return matrix_; }
};
int main ()
{
Parser p;
matrix_t& data1 = *reinterpret_cast<matrix_t*>(p.get_matrix());
const matrix_t& data2 = p.get_matrix_ref();
}
To elaborate on the selected answer, observe this line
const matrix& getMatrix() const
This is great, you don't have to worry about pointers and casting. You're returning a reference to the underlying matrix object. IMHO references are one of the best features of C++, which I miss when coding in straight C.
If you're not familiar with the difference between references and pointers in C++, read this
At any rate, you do have to be aware that if the Parser object which actually owns the underlying matrix object goes out of scope, any code which tries to access the matrix via that reference will now be referencing an out-of-scope object, and you'll crash.