C++ why cannot assign an object created inside constructor? - c++

due project's requirements, by this week I'm shifted from Java to C++. I'm facing a lot of trouble, but maybe the greater is the "pass-by-value" and... obviously pointers :)
Now I have a big doubt regard the destiny of an object instantiated inside an the constructor of another object. Here my simple SSCCE composed by an header and a cpp file:
#pragma once
#include <map>
class MapReferenceHolder
{
std::map<int, char*>* mapPointer;
public:
MapReferenceHolder();
~MapReferenceHolder();
void setMap(std::map<int,char*>* map);
void addSomeElementToMap();
void MapReferenceHolder::printMap();
};
Here the cpp file containing the main:
#include "MapReferenceHolder.h"
#include <iostream>
using namespace std;
std::map<int, char*>mymap;
MapReferenceHolder::MapReferenceHolder()
{
setMap(&mymap);
}
MapReferenceHolder::~MapReferenceHolder()
{
}
void MapReferenceHolder::setMap(std::map<int, char*>* map){
mapPointer = map;
}
void MapReferenceHolder::addSomeElementToMap(){
(*mapPointer)[0] = "stringONe";
(*mapPointer)[1] = "stringTwo";
}
void MapReferenceHolder::printMap(){
std::map<int, char*>::iterator it = mapPointer->begin();
while (it!=mapPointer->end()){
cout << it->first << " -> " << it->second << "\n";
it++;
}
}
int main(){
MapReferenceHolder m;
m.addSomeElementToMap();
m.printMap();
cin.get();
return 0;
}
This simple example run without problem. But if I move the mymap instantiation inside the constructor, i.e.
MapReferenceHolder::MapReferenceHolder()
{
std::map<int, char*>mymap;
setMap(&mymap);
}
I get thw folowing error:
Unhandled exception at 0x00B2BD3B in Project1.exe: 0xC0000005: Access violation reading location 0xCCCCCCD0.
I guess this is due to the fact that an instance of an object live only inside the block in which is defined. But I'm passing the address of object, so it is still alive!?? Or the compiler destroy it in any case? And more important... is it, then, right create a global variable to store an object instance. How I can use correctly the constructor? I know this is a "newbie" question but I'm try to match project's development needs and my spare time to study is really little. Any help will be great appreciated.
Regards,
microvo

The object is destroyed at the end of the constructor. so you have saved a pointer that is no longer valid.

You need to consider ownership in C++ (Java has a cycle detecting garbage collector so gives you a lot of leeway).
If MapReferenceHolder owns the std::map you should make it a value rather than a pointer, you can always use a reference to it if you need a pointer for some reason. Also get rid of your constructor and destructor unless they contain actual code.
Alternatively you could call delete mapPointer in your destructor but that is adding extra code for no benefit in simple cases like this IMO.
If MapReferenceHolder does not own std::map then you need to require the pointer be passed in and somehow track the lifetime of it somewhere outside this class.

The map object no longer exists once it goes out of scope, regardless of any pointers that hold its address - these are no longer valid. I suggest a search for "constructor initializer list" might help you.

Related

How do I create a unique_ptr from a raw pointer, by reference?

I'm calling a library function which returns a raw pointer to a class object, but I'd like to wrap the returned pointer in a unique_ptr. I don't know how the library creates the pointer, but I'm assuming that it uses new (see the comment in the code below).
Is the code below a valid way to create the unique_ptr and return it by reference from a function call? The code does print '42', but is there a better way to do this?
The library is the MariaDB C++ connector. Unfortunately, it has minimal documentation. I asked about this on SO a couple of days ago, but had no response so far. I'd use the MySQL version instead, but it doesn't seem to be much better. However, there is an example program, which includes this line in main:
std::unique_ptr<sql::Connection> conn(driver->connect(url, properties));
So, having read the comments and the answer, I think I can now assume that the Connection object that I want was newed. On the other point, of why I'm passing by reference instead of just returning the unique_ptr - good question. The only reason is that all the other code in this app returns a bool as a success status, so I thought it would be more consistent to do the same here.
Original code:
#include <memory>
#include <iostream>
class A {
public:
int b;
A() : b(42) {}
};
void create(std::unique_ptr<A> &p) {
A *a = new A; // this is actually a function call which returns an A*
p.reset(a);
}
int main() {
std::unique_ptr<A> foo;
create(foo);
std::cout << "foo.b is " << foo->b << '\n';
}
What you wrote works if and only if the pointer is created with new. But even then, just delete'ing it may not be enough to uninitialize it properly, hence why you should always stick to managing this pointer in accordance with the library's documentation.
However, smart pointers are designed to account for cases like this, by allowing you to use a custom deleter function.
So, the proper way would be something like this:
using my_ptr_t = std::unique_ptr<A, void(*)(A*)>;
void create(my_ptr_t& out) {
A* a = ... // get the pointer
out = my_ptr_t(a, [](A* p) -> void {
// Uninitialize the pointer as dictated
// by the library's documentation
...
});
};

Class' methods and objects. Reference? Smart pointers? Simple initialization?

I've been delving into the referenciation and smart pointers over the last couple of days and I still can't figure out when to use which.
Especially for the very simple program I am trying to write.
Where the object value shouldn't be shared but only modified trought returning a value of its type from X or Y methods.
If I am not mistaken, references are easier on the memory, but refers only to one thing.
Where as smart pointers are more stable and can be remaped to point at something else.
First Question:
For simple alterations to an object like in the example bellow, is it even necessary to create a reference or a pointer?
I suppose that in the long run, as the program adds in complexity, having but initialized objects doing their thing could create latency issues and the likes...
Second Question:
As I understand it, refering to an object will aleviate the stress on the memory by refering to the object when used as a parameter in the method instead of copy-pasting the object into it?
Does a smart_ptr does the same-ish?
The header file for class:
-Items.h-
class Health_Potion
{
public:
int qty = 0;
static int add_health_potion(int current, int add);
};
The cpp file for methods:
-Items.cpp-
int Health_Potion::add_health_potion(int current, int add)
{
int new_current = current + add;
cout << add << " potion added to your inventory.\n";
cout << "Quantity available: " << new_current << "\n";
return current + add;
}
The main function:
-Main-
int main()
{
// Initializing the method to be used:
// Question: Should this also be stored into a smart_ptr or referenced to?
Health_Potion add_method;
add_method.add_health_potion;
______________________________________________
// The unique_ptr version I got:
std::unique_ptr<Health_Potion> entity(new Health_Potion); //Unique_ptr
entity -> qty = add_method.add_health_potion(rentity -> qty, roll); //returning new value to the pointer through method
______________________________________________
//The reference version I got:
Health_Potion obj1;
int & refqty = obj1.qty; //reference to object of qty created
refqty = add_method.add_health_potion(refqty, roll); //returning new value to the reference through method
}
Forgive my newbieness.
And thank your for your time :).
I still can't figure out when to use which.
When in doubt, use the simplest approach. Only when the simplest approach is inadequate or awkward is there a reason to consider something more complicated (and at that point, you have a starting point for figuring out which to use).

What is the proper use of dynamic allocation -- should this be avoided? (using new and delete in separate scopes)

I am having trouble understanding proper usage of the new keyword. My question is:
Is the following just bad design as I suspect?
If not, where should I call delete?
If so, what is the better practice?
#include <string>
#include <iostream>
struct myOptions {
int myInt;
std::string myString;
};
myOptions* packageOptions() {
myOptions* options = new myOptions;
options->myInt = 42;
options->myString = "hello world";
return options;
}
int main() {
myOptions* options = packageOptions();
std::cout << options->myString << std::endl;
std::cout << options->myInt << std::endl;
delete myOptions; // this just feels wrong to put here
}
My gut is telling me it's bad because the main function shouldn't have to manage the memory allocated by other functions, as in it's breaking some kind of encapsulation. I thought about doing a class constructor/deconstructor, but that seems to be overkill.
There is no reason to have to chase around memory manually as you are doing. I would just declare your variable on the stack, and return it by value. Then let RAII clean up the memory for you when the variable falls out of scope.
myOptions packageOptions() {
myOptions options;
options.myInt = 42;
options.myString = "hello world";
return options;
}
int main() {
myOptions options = packageOptions();
std::cout << options.myString << std::endl;
std::cout << options.myInt << std::endl;
}
The delete keyword should only appear inside the implementation of smart pointer classes. You can either return by value as Cyber suggested, or in cases where that isn't ideal (for example, return by value causes slicing of derived types) you can return std::unique_ptr and store it in a local variable of the same type, and the destructor will automatically clean up the object and its memory when the pointer goes out of scope.
"Doing a class constructor/destructor" for each case would be overkill. Just take advantage of the existing highly reusable smart pointers.
From a strictly technical perspective, what you are doing is fine.
But you asked what the proper use of new is [in C++] -- and the answer may surprise you.
The most proper way to use new is not to. The same can be said of delete. Instead of using new/delete, you should be using smart pointers such as std::shared_ptr along with an accompanying make_shared.
I'm not saying there are no exceptions, but those exceptions would be unusual and typically the result of a design that could be otherwise modified.
In fact, I would also suggest another question altogether: what is the proper use of dynamic allocation? Again, the answer I would suggest is don't use dynamic allocation. Obviously there are exceptions to this as well, in fact more exceptions than the "don't use new" guideline above -- but as you become more experienced both with the syntax and the semantics of the C++ language, you will find that dynamic allocation is needed in fewer scenarios.
Using shared_ptr is not the best option in your present case. I give this example to show you it exists, and then you don't have to bother about who/when the object is deleted. The shared_ptr will call the destructor/delete whenever there are no references on the object left, ie at the end of main in your example. (also shared_ptr has been introduced in C++11, not available in C++03)
#include <string>
#include <iostream>
#include <memory>
struct myOptions {
int myInt;
std::string myString;
};
using OptionsPtr = std::shared_ptr<myOptions>;
OptionsPtr packageOptions() {
OptionsPtr options = std::make_shared<myOptions>();
options->myInt = 42;
options->myString = "hello world";
return options;
}
int main() {
OptionsPtr options = packageOptions();
std::cout << options->myString << std::endl;
std::cout << options->myInt << std::endl;
}
Anyway, in your case, stack allocation, like in #Cyber answer, is much preferable.
Instead of using structures in this manner, try to use classes and constructors/destructors for the same.
What you have demonstrated is correct as far as managing the memory goes. But stylistically and from a maintenance point of view, it could be much better.
Two ways that are easier to maintain are:
using smart pointers
Redesigning your code so that you pass in a structure to optionsPackage, allowing the function to populate the passed in structure, and the called to worry about the lifespan and usage of the structure.
Smart pointers were created to help prevent memory leaks, which can be a long term pain to find in large projects. Look into std::shared_ptr or see the shared pointers suggested answers.
Passing in the actual structure allows the caller to worry about the memory space used, including allocating and deallocating it. This was the preferred way, before smart pointers came along, and is still the rule of thumb (letting the code that needs the data manage the data object associated with it).
Passing in the actual structure would make the code look something like this:
#include <string>
#include <iostream>
struct myOptions {
int myInt;
std::string myString;
};
void packageOptions( myOptions& theInputOptions) {
theInputOptions.myInt = 42;
theInputOptions.myString = "hello world";
}
int main() {
myOptions options;
packageOptions( options );
std::cout << options.myString << std::endl;
std::cout << options.myInt << std::endl;
}
I find this style far easier to maintain the code. It can be combined with smart pointers where needed.

How do I point at a vector in another class?

I have a class that holds a vector, which also inherits another class:
class txtExt : public extention
{
private:
string openedFile_;
public:
vector<string> txtVector; //the vector i want to call
};
I fill the vector in a method within a class:
class Manager : public extention
{
// there is some other code here that I know does work
// and it calls this function:
void organizeExtention(string filename, string ext)
{
if(ext == "txt")
{
txtExt txtExt;
txtExt.txtVector.pushback(filename);
}
}
}
and this is my main class where i attempt to call the vector:
int main()
{
// some code here that does previous operations like getting the path
// and filling the vector
// I've tried many ways of trying to call the vector
// here is an example of one:
vector<txtExt*> testVector;
for(int i = 0; i < testVector.size(); ++i)
{
cout << testVector[i] << endl;
}
return 0;
}
I have a few questions:
Am I calling the vector wrong?
Is my vector empty?
Do I have to make my vector global, so other classes can see it?
Note: I've been able to print out the vector where I load the vector using a very simple for loop
Well, as has been said you have a few errors in the code posted, and you maybe have some misunderstandings as well. But to answer the question asked, this
testVector[i]->txtVector
is the way to access the txtVector object that is inside each of your txtExt objects.
If that doesn't work for you then it's because one of the other errors/misunderstandings you have in your code.
To summarize:
reread the first chapters of a good C++ book ( The Definitive C++ Book Guide and List ), then try try to fix your program and deal with each error one at the time.
There are several errors in your code.
First of all, there's no operator << for printing entities of the type txtExt*.
Even object of type txtExt is not printable just like that.
In addition, the testVector you made is empty, so no .size() will be zero, and there's going to be no looping.
Are you really sure that you like to inherit both your classes from 'extension' ?
You can't call a vector, you can access it.
Having a data member (like the vector) public is not a good idea.
Calling a variable by the same name as a class is a very bad idea.
I have trouble guessing what your code should do. Here's a simple example of things you need to understand:
#include <iostream>
#include <vector>
#include <string>
class TxtExt
{
public:
std::vector<std::string> txtVector;
};
int main(){
TxtExt oneTxtExt;
oneTxtExt.txtVector.push_back("hello");
oneTxtExt.txtVector.push_back("world");
for( auto &i : oneTxtExt.txtVector ){
std::cout << i <<std::endl;
}
}
The following code is correct, but has absolutely no effect. You could as well just write {}:
{
TxtExt TxtExt;
TxtExt.txtVector.pushback(filename);
}
You here create a new object, push back to it (btw it is called push_back), but then the object is destroyed at the end of the scope. Also, don't name you objects the same as the class, it becomes really confusing.

Cannot set pointer location to that of another pointer's location in C++

I have a method that takes in a reference to a vector that contains pointers to objects as the first parameter, and a reference to a pointer to an object of the same type as the second parameter. Within the method, I want to change the location referenced by the second argument to an object within the vector. Then have the changed pointer be used by the caller of the method, having the new location as its target. However, my current attempts at implementing this are failing.
The method in question:
void execute(std::vector<CanvasElement*>& elements,CanvasElement*& lastFocused)
Examples of ways I've unsuccessfully tried setting the value pointed to by lastFocused:
lastFocused = elements[0];
*lastFocused = *elements[0];
An elaboration in reply to a comment below:
The failure is that the changes inside the function are not reflected once outside the scope of that function.
I can confirm by printing the addresses stored in each pointer during the application's runtime, that the value is indeed being set within execute, but outside of execute it wasn't changed.
The assignment lastFocused = elements[0]; should work, here is a demonstration:
#include <iostream>
#include <string>
#include <vector>
typedef std::string CanvasElement;
void execute(std::vector<CanvasElement*>& elements, CanvasElement*& lastFocused)
{
lastFocused = elements[0];
}
int main()
{
std::string a = "hello";
std::string b = "world";
std::vector<std::string*> vec;
vec.push_back(&a);
vec.push_back(&b);
std::string* p = 0;
execute(vec, p);
if (p == &a)
{
std::cout << "It worked :-)\n";
}
else
{
std::cout << "It did not work :-(\n";
}
}
By the way, there are people who would argue that the following signature would be better:
CanvasElement* lastFocusedCanvasElement(std::vector<CanvasElement*>& elements)
That is, you should return a pointer value instead of changing a pointer variable.
I was able to solve this problem by storing a reference to the pointer in a vector and updating that stored reference. I do not know why setting it directly did not work, but this hack got the job done.