Get space for array with malloc - c++

Trying to pass pointer for array:
class aaa{
public:
int a ;
int b ;
std::string c ;
};
void abc(aaa* a [])
{
*a = (aaa*)malloc(sizeof(aaa)* 5);
a[0]->c ="ddd" ;
a[1]->c ="ccc" ; //crash
a[2]->c ="eee" ;
}
int main() {
aaa * a;
abc(&a);
cout << "!!!Hello World!!!"<< a++->c << endl;
cout << "!!!Hello World!!!"<< a++->c << endl;
return 0;
}
On second array element assignment I have crash. Where is the problem? Does malloc not creates enough space?
UPD.
I can't change function void abc(aaa* a []) signature because of some reason. It is not mistakable signature even it looks not nice.
I have updated program according recomendations in answers, but I still have crash in getting second array element member:
cout << "!!!Hello World!!!"<< a[1].c << endl;
Why? What I do wrong in code below?
struct aaa{
public:
int a ;
int b ;
std::string c ;
};
int abc(aaa* a [])
{
int asize =5;
*a = (aaa*)malloc(sizeof(aaa) * asize);
for (int i;i<asize;i++)
{
a[i] = new aaa();
}
a[0]->c ="ddd" ;
a[1]->c ="ccc" ;
a[2]->c ="eee" ;
return asize;
}
int main() {
aaa * a;
int asize=abc(&a);
cout << "!!!Hello World!!!"<< a[0].c << endl;
cout << "!!!Hello World!!!"<< a[1].c << endl; //crash
cout << "!!!Hello World!!!"<< a[2].c << endl;
for (int i=0; i<asize;i++)
{
cout << "free "<<i<<endl;
a[i].~aaa();
}
free(a);
cout << "end"<<endl;
return 0;
}

The problems are multifold:
mallocing non-POD types so their constructors don't run (catastrophic)
Failure to free the things you malloc (bad)
mallocing in C++ at all (not stylish)
Passing aaa* a[] when you meant aaa** a (valid but misleading)
No #includes, or namespace qualifier on cout and endl (invalid testcase)
Here's what your program should look like:
#include <vector>
#include <string>
#include <iostream>
class aaa
{
public:
int a;
int b;
std::string c;
};
std::vector<aaa> abc()
{
std::vector<aaa> result;
result.reserve(3);
result.push_back({0, 0, "ddd"});
result.push_back({0, 0, "ccc"});
result.push_back({0, 0, "eee"});
return result;
}
int main()
{
const auto a = abc();
std::cout << "!!!Hello World!!!"<< a[0].c << std::endl;
std::cout << "!!!Hello World!!!"<< a[1].c << std::endl;
std::cout << "!!!Hello World!!!"<< a[2].c << std::endl;
}
(Live demo)
Or, to keep your five up-front element allocations:
std::vector<aaa> abc()
{
std::vector<aaa> result(5);
result[0].c = "ddd";
result[1].c = "ccc";
result[2].c = "eee";
return result;
}
I strongly suggest forgetting everything you know about C, when you write C++.

You can use malloc, but you still need to call constructors, for this you need new, this defeats idea of using malloc.
const int asize = 5;
void abc(aaa*& a)
{
a = (aaa*)malloc(sizeof(aaa) * asize); // you need to release memory later
for (int i = 0; i < asize; ++i) {
new (a+i) aaa(); // you need to call constructors to intialize string
}
// now you can use strings
a[0].c = "ddd";
a[1].c = "ccc";
a[2].c = "eee";
}
int main() {
aaa * a;
abc(a);
cout << "!!!Hello World!!!" << a[0].c << endl;
cout << "!!!Hello World!!!" << a[1].c << endl;
// finally you need to call destructors
for (int i = 0; i < asize; ++i) {
a[i].~aaa();
}
free(a);
return 0;
}
After showing you how you can make it work, i would like to propose another solution. If you care about memory and don't want to use std::vector, you can use std::unique_ptr.
std::unique_ptr<aaa[]> data;
data = std::make_unique<aaa[]>(asize);
data[0].c = "text";
cout << data[0].c;
// no need to manually release memory
EDIT:
As of updated question. If you really want to pass array of pointers then you can do the following:
const int asize = 5;
void abc(aaa* a[]) {
// If array is really big, then you probably should preallocate memory and call placement new for every element.
for (int i = 0; i < asize; ++i) {
a[i] = new aaa; // again, you have to release memory
}
// now you can use strings
a[0]->c = "ddd";
a[1]->c = "ccc";
a[2]->c = "eee";
}
int main() {
aaa * a[asize];
abc(a);
cout << "!!!Hello World!!!" << a[0]->c << endl;
cout << "!!!Hello World!!!" << a[1]->c << endl;
for (int i = 0; i < asize; ++i) {
delete a[i];
}
return 0;
}
It would be very nice if you could use unique_ptr instead of raw pointer.

Related

Getting segmentation fault (core dumped) error when declaring a int variable

I was trying to create vector like class. Here is my code
#include <bits/stdc++.h>
using namespace std;
template<class t>
class vec{
t *start;
int size=0;
public:
void add_value(t a){
*(start+(sizeof(t)*size)) = a;
cout << (start+(sizeof(t)*size))<< " = "<< *(start+(sizeof(t)*size))<<endl;
size++;
// cout << start<< endl;
}
void operator [](int i){
cout << (start+(sizeof(t)*i))<< " = "<< *(start+(sizeof(t)*i))<<endl;
}
int length(){
return size;
}
};
int main(){
vec<int> t;
cout << t.length()<<endl;
t.add_value(8);
t.add_value(10);
cout << t.length()<<endl;
t[1];
}
This gives me correct output.
0
0x7fff0fe9b5d0 = 8
0x7fff0fe9b5e0 = 10
2
0x7fff0fe9b5e0 = 10
But when declare a int variable in main function like.
int main(){
int i=0; //newline
vec<int> t;
cout << t.length()<<endl;
t.add_value(8);
t.add_value(10);
cout << t.length()<<endl;
t[1];
}
output.
0
Segmentation fault (core dumped)
I also tried printing address of start variable and new int variable int those are different.
You probably want something like this:
#include <iostream>
using namespace std;
template<class t>
class vec {
t* start = new t[100]; // initialize the pointer (fixed size of 100, to be improved)
int size = 0;
public:
void add_value(t a) {
*(start + size) = a;
size++;
}
t operator [](int i) { // should return a t instead of a void
return *(start + i);
}
int length() {
return size;
}
};
int main() {
vec<int> t;
cout << "t.length() = " << t.length() << endl;
t.add_value(8);
t.add_value(10);
cout << "t.length() = " << t.length() << endl;
// display all values in t
for (int i = 0; i < t.length(); i++)
{
cout << "t[" << i << "] = " << t[i] << endl;
}
}
All multiplication by sizeof(t) have been removed, because pointer arithmetic already does this for you.
This very poor and minimalist example works as you expect, but the maximum number of elements you can store in the class is 100. I leave the improvement as an exercise to you.
BTW there are many other improvements you need to do, especially you need a destructor and possibly the rule of three
Note:
You should replace all instances of *(start + x) with start[x] which does exactly the same thing but which is more idiomatic and more readable.

C++ Deep and Shallow Copy

I need to include shallow copy constructor and I'm completely lost. I thought that the compiler provided a default shallow copy constructor but I have to provide one as well but I'm not sure how to write it. I tried writing it similar to the WrapArrayDeep copy constructor without the pointers but that didn't work. After altering the array both arrays for WrapArrayShallow should be empty.
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#pragma warning(disable: 4996)
using namespace std;
class WrapArrayDeep
{
public:
WrapArrayDeep()
{
capacity = 5;
pca = new char[capacity];
for(int i = 0;i < capacity;i++)
*(pca+i) = (97+i);
} //ends default constructor
WrapArrayDeep(const WrapArrayDeep& wad) //deep copy
{
capacity = wad.getCapacity();
pca = new char[capacity];
for (int i = 0;i < capacity;i++)
*(pca+i) = wad.pca[i];
} //ends copy constructor
~WrapArrayDeep()
{
cout << "destructor for WrapArrayDeep!\n";
delete [] pca;
} //ends destructor
void printArr()
{
for(int i = 0;i < capacity;i++)
cout << pca[i] << " ";
cout << endl;
} //ends print
void alterArr()
{
for(int i = 0;i < capacity;i++)
*(pca + i) = (123+i);
}
int getCapacity() const
{
return capacity;
}
WrapArrayDeep& operator =(const WrapArrayDeep& wad)
{
if(capacity != wad.capacity)
{
delete [] pca;
pca = new char[wad.capacity];
}
capacity = wad.capacity;
for(int i =0;i < capacity;i++)
pca[i] = wad.pca[i];
return *this;
} //end of = operator overload
private:
int capacity;
char *pca;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class WrapArrayShallow
{
public:
WrapArrayShallow()
{
capacity = 5;
pca = new char[capacity];
for(int i = 0;i < capacity;i++)
pca[i] = (97+i);
} //ends default constructor
~WrapArrayShallow()
{
cout << "destructor for WrapArrayShallow!\n";
delete [] pca;
} //ends destructor
void printArr()
{
for(int i = 0;i < capacity;i++)
cout << *(pca + i) << " ";
}
void alterArr()
{
for(int i = 0;i < capacity;i++)
pca[i] = (123 + i);
}
int getCapacity() const
{
return capacity;
}
private:
int capacity;
char *pca;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main()
{
//~~~~~~~~Part 1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cout << "Part 1\n";
int i = 7;
int *pi;
pi = &i;
cout << "i = " << i << endl << "pi = " << pi << endl << "*pi = " << *pi << endl;
cout << "address of i = " << &i << endl << "address of pi = " << &pi << endl;
int **ppi;
ppi = π
cout << "ppi = " << ppi << endl << "*ppi = " << *ppi << endl;
cout << "address of ppi = " << &ppi << endl << "**ppi = " <<**ppi <<endl;
cout << endl << "~~~~~~~~~~~~~~~~~~~~~~~~~~~";
//~~~~~~~~Part 2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cout << "\nPart 2\n";
cout << "This section instantiates a wrapper class for a dynamic array of 5 elements. \n";
WrapArrayDeep wad1, *wad2;
cout <<"WrapArray Deep 1\n";
wad1.printArr();
//deep copy of wad1
wad2 = new WrapArrayDeep(wad1);
cout << "WrapArrayDeep 2 ~ copy constructor \n";
wad2->printArr();
wad1.alterArr();
cout << "after altering WrapArrayDeep1, 1 and 2 = \n";
wad1.printArr();
wad2->printArr();
WrapArrayShallow was1, *was2;
cout << "WrapArrayShallow1\n";
was1.printArr();
//shallow copy of was1
was2 = new WrapArrayShallow(was1);
cout << "\nWrapArrayShallow2\n";
was2->printArr();
was1.alterArr();
cout << "\nafter altering WrapArrayShallow1, 1 and 2 = \n";
was1.printArr();
cout << endl;
was2->printArr();
cout << endl;
delete wad2;
delete was2;
cout << endl;
system("pause");
return 0;
}
To describe at the surface, Deep copy manages every variables including dynamically allocated one and safely copy to the destination object while the shallow copy don't care much about the dynamic variables. You might have a good read
here
When you copy a WrapArrayShallow, there are now two pointers pointing to the same array, and when either WrapArrayShallow is destroyed, you delete[] the array.
Your program exhibits undefined behaviour, it uses a pointer that has been invalidated, when the second WrapArrayShallow is destroyed, and you delete[] pca.
You need to co-ordinate between the different WrapArrayShallow objects such that the last survivor delete[]s the array when it is destroyed. The simplest way is to use a std::shared_ptr<char[]> instead of a char *

Char pointer assignment not working

I have piece of code here.
void MyString::rm_left_space(char *s){
int size = getSize(s);
char s2[size];
char *s1=&s2[0];
int i=0;
while(*(s+i)==' '){
i++;
}
for (int k=i,l=0; k<size; k++) {//start from i, discarding spaces
*(s1+l) = *(s+k);
l++;
}
s=s1;
}
void MyString::rm_right_space(char *s){
int countSpacesfromLast=0;
int size = getSize(s);
int j=size-1;
while(*(s+j)==' '){
countSpacesfromLast++;
j--;
}
char *s2=new char[size-countSpacesfromLast];
for (int t=0; t<size-countSpacesfromLast; t++) {
*(s2+t)=*(s+t);
}
s=s2;
}
void MyString::rm_space(char *s){
rm_left_space(s);
rm_right_space(s);
}
Where there is s=s1 and s=s2 assignment does not happen. How come pointer assignment is not working.
In rm_space method s is unchanged after function calls. Why?
In rm_space method s is unchanged after function calls. Why?
Because s is passed by value. In other words - it's not the variable s that is passed but the value that s holds. The variable s in the called function and the variable s in the calling function are two different variables. Consequently, changes made to one of them does not change the other.
If you want to change s in the calling function inside the called function, you need to use call-by-reference.
Something like:
void MyString::rm_left_space(char*& s){
However, notice that your code have a major problem as it seems you are trying to assign s2 in the called function to s in the calling function. You should never do that as s2 goes out of scope as soon as the function returns.
Example: Difference between pass-by-value and between pass-by-value
This simple program uses pass-by-value
#include <iostream>
void foo(int x)
{
x = 42;
std::cout << "Inside foo: x=" << x << std::endl;
}
int main()
{
int x = 21;
std::cout << "Before foo: x=" << x << std::endl;
foo(x);
std::cout << "After foo: x=" << x << std::endl;
return 0;
}
The output is
Before foo: x=21
Inside foo: x=42
After foo: x=21 // notice x didn't change
because x in foo and in main are two different variables.
This simple program uses pass-by-reference
#include <iostream>
void foo(int& x) // Notice the &
{
x = 42;
std::cout << "Inside foo: x=" << x << std::endl;
}
int main()
{
int x = 21;
std::cout << "Before foo: x=" << x << std::endl;
foo(x);
std::cout << "After foo: x=" << x << std::endl;
return 0;
}
The output is
Before foo: x=21
Inside foo: x=42
After foo: x=42 // notice that x changed
because now x inside foo is a reference to x in main
These examples used int but exactly the same applies for pointers.
Example: Using pointers
#include <iostream>
int x = 21;
int y = 5;
void foo(int* p)
{
*p = 42;
p = &y;
std::cout << "Inside foo: p = " << p << std::endl;
std::cout << "Inside foo: *p = " << *p << std::endl;
}
int main()
{
int* p = &x;
printf("%p\n", (void*)p);
std::cout << "Before foo: p = " << p << std::endl;
std::cout << "Before foo: *p = " << *p << std::endl;
foo(p);
std::cout << "After foo : p = " << p << std::endl;
std::cout << "After foo : *p = " << *p << std::endl;
return 0;
}
Output:
Before foo: p = 0x60106c
Before foo: *p = 21
Inside foo: p = 0x601070
Inside foo: *p = 5
After foo : p = 0x60106c // Pointer value did NOT change
After foo : *p = 42 // Pointed to value DID change
Replacing
void foo(int* p)
with
void foo(int*& p)
will give:
Before foo: p = 0x60106c
Before foo: *p = 21
Inside foo: p = 0x601070
Inside foo: *p = 5
After foo : p = 0x601070 // Pointer value DID change
After foo : *p = 5 // Consequently, the pointed to value also changed
I am new to StackOverflow, if there's any mistake, please Kindly judge me
I am not sure that whether I was misunderstand what you mean, so if there's any misunderstanding, please let me know.
I guess you want to do remove left space in a string, right?
e.g.
" Hello" --> "Hello"
if so, here is my version
#include <iostream>
using namespace std;
#define SIZE 7
void rm_left_space(char* s){
int size = SIZE; //Because I don't know how to getSize, so I use fixed size instead
char s2[size];
char *s1 = &s2[0];
int i = 0;
while(*(s+i) == ' '){
i++;
}
cout << i << endl;
for (int k=i,l=0; k<size; k++) {//start from i, discarding spaces
*(s1+l) = *(s+k);
l++;
}
s=s1; // <-- Shallow copy
}
void rm_left_space_2(char* s){
int size = SIZE;
char *s2 = new char[SIZE]; <-- you should use dynamic array instead of static array
int space_num = 0;
while(*(s+space_num) == ' '){
space_num++;
}
for (int i = 0; i < SIZE; i++){
s2[i] = s[(i + space_num)%size];
}
// s = s2; // <--- shallow copy
for (int i = 0; i < SIZE; i++){ // You should copy whole array
s[i] = s2[i];
}
}
int main(){
char s[] = " hello";
cout << s << endl;
rm_left_space_2(s);
cout << s << endl;
return 0;
}
The output:
hello
hello
Also, you could check the post,
static array vs dynamic array in C++

Looping through array inside of stuct

I'm a student, learning pointers for the first time. My assignment doesn't allow the use of string classes and should be using pointer notation to access all elements within an array (no []).
Why am I not able to access an array inside of a struct via pointers? Is my syntax off?
#include <iostream>
using namespace std;
struct person
{
int favNums[4];
};
// Notation works here
void strCopy(char *from, char *to, int len)
{
for (int i = 0; i < len; i++)
{
*(to + i) = *(from + i);
}
}
// But doesn't work here
void sayNumsPointerNotation(person peep)
{
for (int i = 0; i < 4; i++)
{
//cout << peep.*(favNums + i) << endl;
}
}
// Would like to accomplish this.
void sayNums(person peep)
{
for (int i = 0; i < 4; i++)
{
cout << peep.favNums[i] << endl;
}
}
int main()
{
// Array outside of struct
char from[5] = "Word";
char to[5];
strCopy(from, to, 5);
cout << to << endl << endl;
// Array inside of struct non-pointer
person peep;
peep.favNums[0] = 0;
peep.favNums[1] = 1;
peep.favNums[2] = 2;
peep.favNums[3] = 3;
sayNums(peep);
cout << endl;
sayNumsPointerNotation(peep);
cout << endl;
}
This should work, hopefully you understand what was wrong.
#include <iostream>
using namespace std;
struct person
{
int favNums[4];
};
// Notation works here
void strCopy(char *from, char *to, int len)
{
for (int i = 0; i < len; i++)
{
*(to + i) = *(from + i);
}
}
// But doesn't work here (now it works)
void sayNumsPointerNotation(person* peep)
{
for (int i = 0; i < 4; i++)
{
cout << *(peep->favNums + i) << endl;
}
}
// Would like to accomplish this.
void sayNums(person peep)
{
for (int i = 0; i < 4; i++)
{
cout << peep.favNums[i] << endl;
}
}
int main()
{
// Array outside of struct
char from[5] = "Word";
char to[5];
strCopy(from, to, 5);
cout << to << endl << endl;
// Array inside of struct non-pointer
person peep;
peep.favNums[0] = 0;
peep.favNums[1] = 1;
peep.favNums[2] = 2;
peep.favNums[3] = 3;
sayNums(peep);
cout << endl;
sayNumsPointerNotation(&peep);
cout << endl;
}
Instead of
cout << peep.*(favNums + i) << endl;
Try this:
cout << *(peep.favNums + i) << endl;
Use
cout << *(peep.favNums + i) << endl;
.*, on the other hand, is a "member pointer", and means something different.

C++ how to overload method using pass by value and pass by reference

How do I make the following overload work
#include <iostream>
using namespace std;
int subtractFive (int a)
{
a = a - 5;
return a;
}
int subtractFive (int &a)
{
a = a -5;
return a -5;
}
int main()
{
int A = 10;
cout << "Answer: " << subtractFive(*A) << endl;
cout << "A Value "<< A << endl;
cout << "Answer: " << subtractFive(A) << endl;
cout << "A Value "<< A << endl;
return 0;
}
Tried but doesnt compile
#include <iostream>
using namespace std;
int subtractFive (int a)
{
a = a - 5;
return a;
}
void subtractFive (int* a)
{
*a = *a -5;
}
int main()
{
int A = 10;
cout << "Answer: " << subtractFive(A) << endl;
cout << "A Value "<< A << endl;
subtractFive(A);
cout << "A Value "<< A << endl;
return 0;
}
You might try specifying an overload that takes an address as an argument:
int subtractFive (int *a)
{
*a = *a -5;
return *a -5;
}
Declare one function as pass by address the other by value or reference:
void subtractByFive(int * p_value)
{
if (p_value != NULL)
{
*p_value -= 5;
}
return;
}
A value and a reference have the same type so you can't overload on it. If you want two functions one of which modifies its parameter and one that returns the new value then you either have to give them different names or different types (e.g. make the latter function use a pointer type).