How do I access elements of a an array that is managed by a smart pointer?
I am getting an error
struct has no member xadj
I provided some code below.
I've documentation on smart pointers here
https://www.internalpointers.com/post/beginner-s-look-smart-pointers-modern-c
struct GraphStructure
{
std::unique_ptr<idx_t[]> xadj;
GraphStructure() {
//xadj = new idx_t[5];
std::unique_ptr<idx_t[]> xadj(new idx_t[5]);
}
void function(GraphStructure& Graph) {
int adjncyIndex = 0;
int xadjIndex = 0;
Graph.xadj[xadjIndex] = adjncyIndex;
}
It looks like you have a misnomer about how variables work in c++. In your example, you have 2 different objects of different types named xadj where one shadows the other:
struct GraphStructure {
idx_t* xadj; // A class member object named xadj of type idx_t*
GraphStructure() {
std::unique_ptr<idx_t[]> xadj(new idx_t[5]); // A function scope object called xadj
// that shadows the one above
} // At the end of this scope the xadj unique pointer is destroyed
...
void function(GraphStructure& Graph) {
Graph.xadj[xadjIndex] = adjncyIndex; // Here you use the idx_t* xadj which cannot be
// accessed with operator[], only by derefencing
// (with ->). Even if you did use this accessor,
// it would be undefined behaviour because xadj is
// not initialized.
What you are probably looking for is something like this:
struct GraphStructure {
std::unique_ptr<idx_t[]> xadj;
GraphStructure() : xadj(new idx_t[5]) {}
};
Related
I am making a game with a separate map class and a separate renderer class for rendering the map.
Here is a simplified version of what that looks like: (the function I am interested in is renderMap()
#include <iostream>
#include <vector>
class Map
{
public:
Map(int mapSize)
: data(mapSize,3) {} //Initialize the vector with the requested size, filled with 3's. Just as an example
//Accessors
const std::vector<int>& accessData() { return data; }
private:
std::vector<int> data;
};
class Renderer
{
public:
void setPointerToMap(Map& map) { pointerToMap = ↦ }
void renderMap()
{
// Here some of the calls to the map object might become really long, especially if the vector "data" contains objects and we need to access the objects
// So can we somehow create a short alias for "pointerToMap->accessData()"?
// So that instead of "pointerToMap->accessData()[0]" we write "dataPoint[0], for example
std::cout << pointerToMap->accessData()[0];
}
private:
Map* pointerToMap;
};
int main()
{
Map map(5); // Create map object
Renderer renderer; // Create renderer object
renderer.setPointerToMap(map); // "Attach" the map to the renderer by giving the renderer a pointer to the map
renderer.renderMap(); // Render the map in the renderer using the pointer to the map to read the data
}
So basically I read the data of Map inside Renderer using a pointer to the map object.
I've read about using keyword and function pointers, but can't figure out if they are intended to be used for this.
I tried making a function pointer like this:
std::vector<int>& (Map:: * dataPoint)() = pointerToMap->accessData;
but this gives an error
error C3867: 'Map::accessData': non-standard syntax; use '&' to create a pointer to member
and Visual Studio says that "a pointer to a bound function may only be used to call the function.
So I guess it is simply not possible to create a function pointer if we access the function with a pointer?
If we make the data vector public, then we can access it:
std::vector<int>& dataPoint = pointerToMap->data;
std::cout << dataPoint[0];
But that's not exactly what I need in my actual game.
Bonus: Here is the other way that I managed to create a function pointer inside renderMap(), yet I don't understand how it works and it doesn't really work correctly:
std::vector<int>& (Map:: * dataPoint)() = &Map::accessData;
std::cout << dataPoint;
So the question is, is it possible to shorten the function calls in this case and how?
Instead of calling accessData on each line, simply create a reference and use it for all other lines:
const std::vector<int>& dataPoint = pointerToMap->accessData();
std::cout << dataPoint[0];
Here you create a new variable that is a reference to the vector returned by accessData.
If I create a class in c++, it is possible to call a function of an object of this class, even if this class does not exists.
For example:
Class:
class ExampleClass
{
private:
double m_data;
public:
void readSomeData(double param)
{
m_data = param;
}
}
Any function where this class is used:
int main()
{
ExampleClass* myClass;
myClass->readSomeData(2.5);
}
Ofcourse this wouldn't function, because myClass is not defined.
To avoid such situations, I check if ExampleClass objects are a null_ptr
example:
void readSomeData(double param)
{
if(this == null_ptr)
return;
m_data = param;
}
But gcc says:
'this' pointer cannot be null in well-defined C++ code; comparison may
be assumed to always avaluate to false.
Ofcourse that is only a warning, but I think it is not nice to have this warning. Is there a better way to check if the pointer of a class is defined?
Testing it in the class is the wrong way, the warning is correct about that if your code is well defined then this must not be null, so the test should happen at the time when you call the member function:
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
if (myClass != nullptr) {
myClass->readSomeData(2.5);
}
return 0;
}
If a pointer must not be null at a certain part of your code then you should do it according to CppCoreGuideline: I.12: Declare a pointer that must not be null as not_null
Micorosoft provides an Guidelines Support Library that has an implementation for not_null.
Or if possible then don't use pointers at all but std::optional.
So a code setup could look like this:
#include <gsl/gsl>
struct ExampleClass {
void readSomeData(double ){}
};
// now it is clear that myClass must not and can not be null within work_with_class
// it still could hold an invalid pointe, but thats another problem
void work_with_class(gsl::not_null<ExampleClass*> myClass) {
myClass->readSomeData(2.5);
}
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
work_with_class(myClass);
return 0;
}
The best way is not use pointers at all:
int main()
{
ExampleClass myClass;
myClass.readSomeData(2.5);
}
That way there's no need for any check, and in fact, checking this inside the function is moot.
If you need nullability, use std::optional instead.
Either don't use pointers as Bartek Banachewicz has pointed out, or properly initialize and check the pointer:
int main()
{
ExampleClass* myClass= 0;
if (myClass)
myClass->readSomeData(2.5);
return 0;
}
Of course you still have to add the instantiation of the object at some point, otherwise the code is nonsense.
I'm having a small problem which I can't wrap my head around.
I have a function that looks like this:
template <typename T>
std::unique_ptr<Environment>& CreateEnvironment(sf::Vector2f& _position, bool _addToStatic = false);
This is my function pointer typedef
typedef std::unique_ptr<Environment>& (WorldEditor::*CreateEnvironmentPtr)(sf::Vector2f&, bool);
std::map<std::string,CreateEnvironmentPtr> listEnv;
And I'm trying to simply do this:
listEnv["test"] = &CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
And i get the following error:
error C2440: '=' : cannot convert from 'std::unique_ptr<_Ty> *' to
'std::unique_ptr<_Ty> &(__thiscall WorldEditor::* )(sf::Vector2f
&,bool)'
I understand what the error is saying, but I don't know how to solve it. Also why does it even care about the return type when I'm pointing to the address of the function?
Best regards
nilo
problems such as these are often much better solved with std::function
std::map<std::string, std::function<void()> listEnv;
listEnv.emplace("test", [] {
CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
});
to call:
listEnv.at("test")->second();
Based on your post I am not sure if you are attempting to create the member function pointer and map inside the CreateEnvironment class or outside of it, so I'll solve what I think is the more difficult problem of pointer to a separate object's member function.
I simplified your classes like so:
Environment
struct Environment
{
int i = 1;
};
Coin
struct Coin
{
int k = 0;
};
WorldEditor
struct WorldEditor
{
template <typename T>
std::unique_ptr<Environment> CreateEnvironment(int& _j, bool _addToStatic = false)
{
return std::make_unique<Environment>();
}
};
Solution: Map an object's member fn pointer, and then call it later
(I will be using C++11/14 syntax in my answer)
//declare a pointer to member function in WorldEditor
using CreateEnvironmentPtr = std::unique_ptr<Environment> (WorldEditor::*)(int&, bool);
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to the CreateEnvironment<Coin> function
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = &WorldEditor::CreateEnvironment<Coin>;
// call the member function pointer using the instance I created, as well as
// the mapped function
(myWorldEditor.*listEnv["test"])(myInt, false);
// (printing member value to cout to show it worked)
std::cout << (myWorldEditor.*listEnv["test"])(myInt, false)->i << std::endl; // prints 1
Live Demo
Solution 2: use std::bind and std::function
Perhaps we already know the parameters to the member function call at the time we create the entry for map. Using std::bind with a std::function will help us achieve that (Similar to Richard Hodges' solution):
// now our "function pointer" is really just a std::function that takes no arguments
using CreateEnvironmentPtr = std::function<std::unique_ptr<Environment>(void)>;
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to that function pointer
//ensure it gets called with the right args
// by using std::bind (which will also make the arg list appear the be void at call time)
// note that std::bind needs an instance of the class immediately after
// listing the function it should be binding
// only afterwards will we then pass the int& and bool
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = std::bind(&WorldEditor::CreateEnvironment<Coin>, &myWorldEditor, myInt, false);
// the mapped function
listEnv["test"]()->i;
// (printing resulting unique_ptr<Environment>'s member to cout to show it worked)
std::cout << listEnv["test"]()->i << std::endl; // prints 1
Live Demo 2
Given a C++ class with assorted member data values and a static int counter, I'd like to have a clear() function that can walk all the elements of an array of these class objects clearing their data members.
So, for example, a class that looks like this and holds a chip's version information (yes, I know I probably need more setters and getters):
class __STA_version_t
{
public:
__STA_version_t() { count++; };
~__STA_version_t() {};
void setVerString( char* x ) { strncpy( verString, x, sizeof(verString)); verString[sizeof(verString)-1] = 0
void clearVerString() { memset( verString, 0x0, sizeof(verString) ); }
char* getVerString() { return verString; }
bool hasVersion() { return verString[0]; }
void clear()
{
for ( int i = 0; i < count; i++ )
{
// what goes here?
}
}
private:
static int count; // how many of these objects exist, need to know for clear().
char verString[20]; // station version as a string
UINT8 major_ver; // major version identifier (3 bits)
UINT8 minor_ver; // minor version identifier (6 bits)
UINT8 revision; // revision identifier (4 bits)
UINT8 chip_ident; // target chip identifier (3 bits)
};
Elsewhere initialize count thusly:
__STA_version_t::count = 0;
Now, create an array of there objects:
__STA_version_t versions[10];
First, just checking, count should equal 10 after this instantiation, right?
In the clear() function, I'd like to say something like:
this[i]->clearVerString();
this[j]->revision = 0;
// etc.
to clear each data member of each element of the array.
Can this be made to work? How?
The issue is that the class can't see outside its boundaries and the container is outside of the class' boundary.
You should use a standard container. Make the clear method clear data members in the class.
The standard containers have methods for determining the number of items.
See std::vector, std::list, std::map, etc.
What you are trying to do is not very "object oriented" IMO. I would argue that the class clear() member function you are trying to implement here should only clear the data of the instantiated object on which it is invoked. What you are trying to do is clear the data in all instantiations of your class, via calling clear() on any/one of them only?
A better approach here would be to store your objects in a std::vector<__STA_version_t>, and then write a static function on your class that either takes the vector as a parameter (ideally), or can access it globally somehow, called maybe clearAll(). Have that function iterate through the vector and call clear() on each object in the vector. The clear() function would then simply call clearVerString() etc on itself - eg:
this->clearVerString();
this->revision = 0; and so on (noting that you don't actually need to use the this pointer if you don't want to).
I'm having some trouble refactoring a class that uses a std::vector of unique_ptrs. I currently have a class similar to:
class DataItemA
{
// various data members
};
class DataItemB
{
// various data members
};
class PointerOwner
{
public:
PointerOwner();
~PointerOwner();
void ComplexCalculationOnItemA()
{
for (auto itr = aItemsIOwn.begin(); itr != aItemsIOwn.end(); ++itr)
{
DataItemA& itemA= (**itr);
// complex calculations that also reference DataItemB items
}
}
// methods to add / remove items from the collections
private:
// This class owns the DataItems and control their lifetime.
// The objects cannot live outside of this instance.
std::vector<std::unique_ptr<DataItemA>> aItemsIOwn;
std::vector<std::unique_ptr<DataItemB>> bItemsIOwn;
};
I was refactoring the class to extract the complex calculation to another class and was unsure how to pass the vector of unique_ptrs to the other class and clearly 'state' that the calculation does not own the pointers. Is it reasonable to:
class ComplexItemAProcessor
{
ComplexItemAProcessor(const std::vector<std::unique_ptr<DataItemA>>& itemsToProcess)
{
// can I store the itemsToProcess in a member variable
}
SomeReturnType runCalcuation() {}
private:
// store the reference to calculation
}
Or is this better which can be done:
class ComplexItemAProcessor
{
ComplexItemAProcessor()
{
}
SomeReturnType runCalcuation(const std::vector<std::unique_ptr<DataItemA>>& itemsToProcess)
{
// process the collection as per original class
}
}
The lifetime of the ComplexItemAProcessor would be limited to scope of the original method.
class PointerOwner
{
public:
PointerOwner();
~PointerOwner();
ComplexCalculationOnItemA()
{
ComplexItemAProcessor processor; /** ? pass here **/
SomeReturnType result = processor.runCalcuation(/* ? pass here */);
}
private:
// This class owns the DataItems and control their lifetime.
// The objects cannot live outside of this instance.
std::vector<std::unique_ptr<DataItemA>> aItemsIOwn;
std::vector<std::unique_ptr<DataItemB>> bItemsIOwn;
};
Is either of these better than the other? Neither feels right to me, but that could be my limited experience with smart pointers in general. Is there another way for another class to process the vector without transferring ownership?
I don't think I need shared_ptrs as PointerOwner is the only owner.