Using explicit/raw pointers in c++ - c++

I read that using raw pointers in C++ is bad. Instead we should use auto_ptr. In the below code I am populating a vector in foo() that is created in the main(). Am I doing it right or is there a better way to do without using explicit pointers.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void foo(vector<string> *v){
(*v).push_back(" hru");
}
int main(){
vector<string> v;
v.push_back("hi");
foo(&v);
for(int i=0;i<v.size(); i++){
cout << v[i];
}
}

C++ uses references for what you are trying to do:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void foo(vector<string>& v){
v.push_back(" hru");
}
int main(){
vector<string> v;
v.push_back("hi");
foo(v);
for(int i=0;i<v.size(); i++){
cout << v[i];
}
}
References and pointers are similar, with one very important distinction: there is no such thing as a null reference (Constructing one is Undefined Behavior in C++ you can construct one, but doing so is considered a hack).

In C++ you can avoid the pointer and use a pass-by-reference:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void foo(vector<string>& v){
v.push_back(" hru");
}
int main(){
vector<string> v;
v.push_back("hi");
foo(v);
for(int i=0;i<v.size(); i++){
cout << v[i];
}
}

You can begin to think about using auto_ptr when you deal with objects created on heap (e.g. a class instance created by "new"). Your vector holds its elements by value, std::string elements it is. So you don't need to consider auto_ptr here at all. If your vector would hold instances created on heap then you could use something like this:
std::vector< auto_ptr< MyType > > vec;
auto_ptr< MyType > a( new MyType() );
vec.push_back( a );
and then when your vector elements get erased by e.g. your vec leaving its scope then instance 'a' will get deleted automatically.
With other words, auto_ptr is a kind of garbage collector which does a kind of automatic object deletion for you. See here for more information about auto_ptr http://www.cplusplus.com/reference/std/memory/auto_ptr

Related

How can I declare a stack reference in C++11?

I am implementing a stack reference. However I got the error of 'Segmentation fault (core dumped)'. I am using g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2 on Ubuntu 14.04. Many thanks.
The code is listed below.
#include<iostream>
#include<stack>
using namespace std;
int main() {
stack<int>* S;
S->push(4);
return 0;
}
Stop using new wherever you can.
#include <iostream>
#include <stack>
int main() {
std::stack<int> s;
s.push(4);
return 0;
}
Having "naked" pointers representing object ownership is generally discouraged, as it is error-prone. Either use automatic variables, or the smart pointers provided by the library.
#include <stack>
#include <memory>
int main()
{
// On the stack, local scope. This is the fastest;
// unlike Java we don't have to "new" everything.
std::stack<int> s1;
s1.push(4);
// Dynamically allocated, gets auto-deleted when the
// last copy of the smartpointer goes out of scope.
// Has some overhead, but not much.
// Requires some extra plumbing if used on arrays.
auto s2 = std::make_shared<std::stack<int>>();
auto s2_copy(s2); // can be copied
s2->push(4);
// Dynamically allocated, gets auto-deleted when the
// smartpointer goes out of scope. No overhead, but
// cannot be copied / shared.
// Works out-of-the-box with arrays as well.
auto s3 = std::make_unique<std::stack<int>>();
s3->push(4);
}
you have to create the object then you can point to it.
#include<iostream>
#include<stack>
using namespace std;
int main() {
stack<int> s;
stack<int>& S = s;
S.push(4);
return 0;
}

C++ Dynamic Array Member Variable Assignment

I am having a problem with assigning new values to a dynamic int array that is a data member variable of the class IntersectionFlowRate(). I can initialize and print the values of the array inside the constructor. However, when I exit the constructor to the another class and then later call a function within the IntersectionFlowRate() class passing in variables to overwrite the initial values of the data member it will segmentation fault. I have debugged to find that overwriting the array is causing the seg fault. And that even attempting to access the dynamic array within one of its functions will seg fault.
My question is how can I edit the values of a dynamic int array member variable from within one of its functions i.e setArrayElement(int index, int x).
Here is some of my code. Sorry if I am unclear or missing something ridiculous. I have been stuck on this for hours.
#ifndef INTERSECTIONFLOWRATE_H
#define INTERSECTIONFLOWRATE_H
class IntersectionFlowRate
{
public:
IntersectionFlowRate();
~IntersectionFlowRate();
void setFlowCycle(int index, int flow);
private:
int* m_flowRateMotorCycle;
};
#endif
in the .h file ^
#include "IntersectionFlowRate.h"
#include <cstdlib>
#include <iostream>
#include <new>
using namespace std;
IntersectionFlowRate::IntersectionFlowRate()
{
const int SIZE = 4; //Constant for m_flowRates[] size
//DYNAMIC MEMORY DELETE LATER
m_flowRateMotorCycle = new int[SIZE];
for(int i = 0; i < SIZE; i++){
m_flowRateMotorCycle[i] = 0;
cout << m_flowRateMotorCycle[i] << endl;
cout << "WE GOT HERE" << endl;
}
}
void IntersectionFlowRate::setFlowCycle(int index, int flow){
cout << "INDEX: " << index << endl;
cout << "FLOW: " << flow << endl;
m_flowRateMotorCycle[index] = flow; //seg fault is here
}
I have another class that creates a pointer to a IntersectionFlowRate() object and then calls its setFlowCycle function passing in two VALID ints. With the debugging I was able pass 0 and 3 to the function setFlowCycle(0, 3) just fine and output those variables within the function.
#ifndef TRAFFICSIM_H
#define TRAFFICSIM_H
#include "IntersectionFlowRate.h"
using namespace std;
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
~TrafficSim(); //Destructor
private:
IntersectionFlowRate* m_flowRate;
};
#endif
#include "TrafficSim.h"
#include "IntersectionFlowRate.h"
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
I replicated the error with this code. If no one else can I am completely unsure of what is possibly wrong anymore.
You are setting a local variable called m_flowRate, not the member variable m_flowRate of your TrafficSim class:
Instead of this:
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
It should be this:
TrafficSim::TrafficSim()
{
m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
But overall, it not need be a pointer. It could be an object member within your class. That would cut down on the pointer usage a bit:
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
private:
IntersectionFlowRate m_flowRate;
};
Then:
TrafficSim::TrafficSim()
{
m_flowRate.setFlowCycle(0, 3);
}
As to your question as to how to incorporate usage of std::vector in your class, here is a code sample of the IntersectionFlowRate class, rewritten using vector:
Vector sample
Also, another source of problems is that your classes fail to follow the Rule of 3 when you have pointers to dynamically allocated memory in your class.
Using std::vector takes care of this automatically, but if you insist on using pointers, you need to adhere to the directions at the link posted.
Yes, use a std::vector, it is much simpler, and it is a template so it also pretty fast and works any type (best for primitive types or pointers to objects) , and it also has boundary checking and other useful things.
If you need fast array-like access then you could use std::map which associates a key with a value, like so
std::map<UINT, YourClass*> m_mapIDs_to_YourClass;
When you first start using stl containers they might seem a little strange, but after a short while you cannot do without them, luckily they have been part of the C++ standard for some time now.
Boundary check for both these containers can be done by comparing your iterator to mapYourMap.end(), if they are equal you have passed the last element and trying to access data through the iterator will cause an exception.
Example for std::vector (if vecInt is a vector< int >):
vector<int>::iterator it = vecInt.begind();
if (it == vecInt.end()) return; // vector is empty
do { // runs through elememts until out of bound, useful for searching
i++
while (it != vecInt.end());

C++ STL vector init

I am just wondering how I could solve this problem.
I have a
vector<char> vstr;
definition in the class Program.
Then in the class constructor I want to init this vector with an array:
char arrayOfChars[] = {'a', 'b', 'c'};
this.vstr = new vector<string>(arrayOfChars, arrayOfChars + sizeof(arrayOfChars)/sizeof(arrayOfChar[0]));
The build gives me a bug:
error: request for member 'vstr' int 'this', which is of non-class type 'Program *const' .
Could you give me a simple solution for this error?
I'm not an expert in C++ but I see at least two problems:
You are trying to initialise an object with a pointer. Don't use new key word.
What is more this pointer points to vector of strings not chars, so replace vector<string> with vector<char>.
As melak47 says in his comment this.vstr is also incorrect because this is a pointer and therefore should be replaced with this->vstr or simply vstr
Once you make all the three corrections it should compile
I think that piece of code is what you want.
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
class Program {
vector<char> vstr;
public:
Program(const char* data)
{
string s(data);
std::copy(s.begin(), s.end(), std::back_inserter(vstr));
}
void PrintData()
{
for (auto it = vstr.begin(); it != vstr.end(); it++)
{
std::cout << (*it);
}
}
};
int main()
{
Program p("simple data");
p.PrintData();
}

Passing pointer to dynamically allocated array by copy to function has unexpected result

I was just messing around with passing pointers to functions to wrap my head around how it works and I came across some behavior that was unexpected. I have the following code:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <iomanip>
using namespace std;
struct t
{
string x;
string y;
};
void foo(t*);
int main()
{
t* ts = new t[2];
ts[0].x = "t1.x";
ts[0].y = "t1.y";
ts[1].x = "t2.x";
ts[1].y = "t2.y";
foo(ts);
cout << ts[0].x << endl;
}
void foo(t* s)
{
delete[] s;
s = new t[2];
s[0].x = "FOO.X";
s[1].y = "FOO.Y";
}
The output here, interestingly enough, is "FOO.X". I expected that since inside of foo, s is a copy of the pointer ts that when I delete[] s I effectively delete[] ts as they both point to the same address. Then s = new t[2]; should have no effect on ts. After foo returns, I should no longer have access to s or the array it points to and ts should point to who knows where. Am I missing somehthing?
Note: This is just a test project that I made where I constantly write and erase blocks of code to test different concepts. All the includes and using namespace std is for ease of use, and it is NOT code that I am writing for any sort of practical use, purely educational. Also, I am using MS VS 2013.
Try changing your foo() like this and see the result:
void foo(t* s)
{
delete[] s;
// Additional memory allocation
t* u = new t[2];
s = new t[2];
s[0].x = "FOO.X";
s[1].y = "FOO.Y";
}
By adding another memory allocation, I moved s to another location in the memory, which is not anymore overlapping with ts. Otherwise, s was simply allocated at the same location where ts previously resided.
As pointed out in the comments, you are observing an undefined behavior, which you should by no means rely on. The example above illustrates that pretty well.

C++ Vectors and struct pointers

My struct has a vector of integers. However, when dynamically creating an instance of the struct, I can't seem to access the vector.
#include <stdlib.h>
#include <iostream>
#include <vector>
using namespace std;
typedef struct {
vector<int> intList;
} astruct;
int main()
{
astruct* myStruct = (astruct*) malloc(sizeof(astruct));
myStruct->intList.push_back(100);
cout << "Hello world!" << endl;
free(myStruct);
return 0;
}
Attempting to add 100 to the struct's vector crashes the program. Hello world! is never shown. What's going on?
Your vector is never initialized as you simply cast an allocated memory region to a astruct*, therefor the constructor of your struct and as consequence the constructor of std::vecotr is never called. Use the new operator instead.
astruct* myStruct = new astruct();
myStruct->intList.push_back(100);
delete myStruct;
You should not use malloc()/free() in C++ program, especially for creating C++ object, unless you know what you are doing. So use new/delete instead:
int main()
{
astruct* myStruct = new astruct;
myStruct->intList.push_back(100);
cout << "Hello world!" << endl;
delete(myStruct);
return 0;
}