How can we initailize a struct pointer in constructor of a class.
Example:
struct my_struct{
int i;
char* name;
};
class my_class{
my_struct* s1;
my_class() {
// here i want to make s1->i = 10; and s1->name = "anyname" ;
// should i assign it like s1->i= 10; and call new for s1->name and strcpy(s1->name "anyname");
// it compiles in g++ without any warning/error but gives seg fault at run time
}
};
I'm surprised that no-one has suggested the following...
struct my_struct
{
int i;
std::string name;
my_struct(int argI, std::string const& argName) : i(argI), name(argName) {}
};
class my_class
{
my_struct s1; // no need for pointers!
my_class() : s1(1, std::string("test name")) {} // construct s1 using the two argument constructor, can also default construct as well.
};
With this approach, you don't need to worry about cleaning up s1, it's automatic...
When you create an instance of my_class, the s1 pointer doesn't point to anything. You have to allocate memory for it like so:
myclass() {
s1 = new my_struct;
// initialize variables
}
You will also have to create a destructor for it:
~myclass() {
// delete variables
delete s1;
}
Also, since this is C++, I recommend you use std::string instead of char*s.
Since this is C++, use std::string instead of char*:
struct my_struct{
int i;
std::string name;
};
class my_class{
my_struct* s1;
my_class() {
s1 = new my_struct;
s1->i = 10;
s1->name = "anyname";
}
};
The reason your original code segfaulted was that you failed to allocate memory for s1 and also failed to allocate memory for s1->name. I've fixed the former with the new and the latter by using std::string. If for some reason you can't use std::string, use strdup where you were trying to use strcpy.
Lastly, don't forget to provide a destructor for my_class that'll delete s1 (and will free s1->name if you opt for char* and strdup).
I'm pretty sure you can use an initialization list, and new+init the struct directly. Also, you can't forget that you have to delete the pointer when you're done:
struct my_struct{
int i;
char* name;
};
class my_class{
my_struct* s1;
my_class() : s1(new my_struct) {
s1->i = 2;
s1->name = "Something";
}
~my_class() { delete s1; }
};
Also, make sure you're using a char* for a reason, otherwise a std::string will most often be better.
If the structure is inside the class, you can use the structure constructor:
struct my_struct
{
int i;
std::string name;
my_struct()
{
i = 10;
name = "anyname";
};
};
If it's global, you first need to create the object and then initialize it:
class my_class
{
my_struct * s1;
my_class() : s1(new my_struct())
{
s1->i = 10;
s1->name = "anyname";
}
};
my_class() {
s1 = new (my_struct);
s1->i = 10;
s1->name = (char *) malloc(strlen("anyname"));
s1->name = "anyname";
// here i want to make s1->i = 10; and s1->name = "anyname" ;
// should i assign it like s1->i= 10; and call new for s1->name and strcpy(s1->name "anyname");
// it compiles in g++ without any warning/error but gives seg fault at run time
}
~my_class(){
free(s1->name);
delete s1;
}
Related
I have this code:
class myclass
{
std::string str;
public:
void setStr(std::string value)
{
str=value;
}
std::string getStr()
{
return str;
}
}
main()
{
myclass ms;
std::cout<<ms.getStr()<<std::endl;
}
when I compile and run this code, there is o error and in windows I am always getting str as "".
Is this always valid?
I need the above behavior in the fact that if user did not call set, str would be always a blank string.
should I initialize str in constructor as follow:
class myclass
{
std::string str;
public:
myclass():str(""){}
void setStr(std::string value)
{
str=value;
}
std::string getStr()
{
return str;
}
}
I want to make sure that behavior is the same on all platform and also make sure that code is as small and neat as possible.
Do I need to initialize std::string
No. std::string default constructor initialises a nice empty string for you.
I want to make sure that behavior is the same on all platform and also make sure that code is as small and neat as possible.
Remove clutter then:
struct myclass {
std::string str;
};
Fundamental types though, do not get initialised by default, you need to initialize them explicitly:
struct myclass {
std::string str;
int i = 1; // <--- initialize to 1.
};
You dont need to initialize a string member with an empty string, though it can help to do it anyhows. Consider:
struct foo {
std::string a;
std::string b;
foo() : a("foo") {}
};
Was it by accident or on purpose that b does not get a value in the constructor? I'd prefer
foo() : a("foo"), b() {}
because it makes the intend explicit for no price (not counting a few keystrokes).
So I have my class Test.H which has a struct in it.
Class Test{
private:
struct Data
{
char *first;
int number;
int count;
};
Data *myStruct;
I am trying to use the myStruct in my User.C initialiser.
//User.C
#include "Test.H"
Test::Test(const char *alp){
myStruct.number = 0;
}
And I get an segmentation fault and error from valgrind.
I figured initially that it was due to Data* myStruct being in private, but after writing a function like this below:
Data getStruct(){
return myStruct;
}
It will still give me errors when I use it in User.C
You need to construct the struct before you can do anything with it. Calling the default constructor will initialises it's fields to 0.
You had class capitalised, that was wrong. I also don't see a reason why it has to be a pointer, so I removed that. Lastly, I added a destructor in Data so that first will be deleted. I assume it is a cstring, so I used delete[]. If it is something else, delete it in whatever manner is appropriate.
If you must have a pointer, modify the call to the constructor to use new, delete the struct in the destructor ~Test(), and reference members of myStruct with the -> operator.
class Test {
public:
struct Data {
const char* first;
int number;
int count;
~Data() {
delete[] first;
}
};
Test(const char *alp) {
// Default constructor initialises struct's fields to 0.
myStruct = Data();
myStruct.count = 7;
}
private:
Data myStruct;
};
Good morning.
Question is about initialisation of object.
Its easy to do like this:
class MyClass {
char* data;
public:
inline MyClass(char* s) {
data = s;
};
}
MyClass Obj = "foo";
But is it possible to make initialization syntax(with the same actions) like this?
MyClass Obj[] = "foo";
I need brackets for compatibility with other compiler :/
Have you tried using the initialization list using {} ?
MyClass Obj[] = {"foo"};
or
MyClass Obj[] = {"foo", "bar"};
I run in to segmentation faults when running this code (no compiler warnings or errors).
It occurs when trying to assign "Test" to str->sString
MyClass.cpp
//Constructor
MyClass::MyClass( MyStruct *pDesc )
{
pDesc = new MyStruct();
//This is where I get a segmentation fault
pDesc->bar= 0xFF;
}
MyClass.hpp
class ClGadgetFs
{
public:
struct MyStruct{
int bar;
};
MyClass(MyStruct *pDesc = NULL);
};
I thought when calling new I would be aalocating memory for the struct? Like malloc(sizeof(myStruct))
Where am I wrong?
void setStruct(myStruct *str)
{
str->sString = "Test";
str->nNo = 4;
}
int main()
{
myStruct p;
setStruct(&p);
return 0;
}
you can do this instead
Edit
int main()
{
MyStruct *pDesc;
MyClass myClassInstance( pDesc );
std::cout<< pDesc->bar << std::endl;
return 0;
}
and
MyClass::MyClass( MyStruct *pDesc )
should be changed to
MyClass::MyClass( MyStruct *& pDesc )
void setStruct(myStruct*& str)
The above is probably what you want: changing the passed pointer, as output parameter.
#include <string>
struct myStruct
{
std::string sString;
int nNo;
};
void setStruct(myStruct **str)
{
*str = new myStruct();
(*str)->sString = "Test";
(*str)->nNo = 4;
}
int main()
{
myStruct *p;
setStruct(&p);
}
should be what you want, this is the C-style of passing the pointer; since you're allocating memory for the passed pointer, passing the pointer alone doesn't work, you should pass the pointer's address. Another way would be a reference to the pointer that Joop Eggen's answer points out.
str in the function setStruct is a local variable, whose life time is limited in this function.
So when new returns the address, there is no effect on the actual parameter. It is just the same to
void func(int a){
a = 4
}
You should use pointer to pointer or reference
void setStruct(myStruct ** str){
(*str) = new myStruct();
(*str)->sString = "Test";
(*str)->nNo = 4;
}
void setStruct(myStruct *& str){
str = new myStruct();
str->sString = "Test";
str->nNo = 4;
}
You should use a reference to your pointer to modify it in your function:
struct myStruct{
std::string sStrnig;
int nNo;
};
void setStruct(myStruct* &str){
str = new myStruct();
str->sString = "Test";
str->nNo = 4;
}
main(){
struct myStruct *str = 0;
setStruct( str );
}
It's likely that the caller of setStruct is allocating a myStruct on the stack:
myStruct value;
and you are calling setStruct(&value);
That would cause the segmentation fault as you would be attempting to rearrange the stack memory.
It's difficult to say anything else without the complete example though.
There's nothing wrong with the code as it stands aside from the fact that the value of the pointer following str = new myStruct(); is not passed back to the caller: the caller would be still referring to the pointer pointing to unallocated memory which would result in undefined behaviour. But that is not causing your crash since given where you say the error happens.
A simple fix would be to change the function prototype to
void setStruct(myStruct*& str)
i.e. pass the pointer by reference so the caller get's the modified pointer value back.
I have a class called Object which stores some data.
I would like to return it by reference using a function like this:
Object& return_Object();
Then, in my code, I would call it like this:
Object myObject = return_Object();
I have written code like this and it compiles. However, when I run the code, I consistently get a seg fault. What is the proper way to return a class object by reference?
You're probably returning an object that's on the stack. That is, return_Object() probably looks like this:
Object& return_Object()
{
Object object_to_return;
// ... do stuff ...
return object_to_return;
}
If this is what you're doing, you're out of luck - object_to_return has gone out of scope and been destructed at the end of return_Object, so myObject refers to a non-existent object. You either need to return by value, or return an Object declared in a wider scope or newed onto the heap.
You can only use
Object& return_Object();
if the object returned has a greater scope than the function. For example, you can use it if you have a class where it is encapsulated. If you create an object in your function, use pointers. If you want to modify an existing object, pass it as an argument.
class MyClass{
private:
Object myObj;
public:
Object& return_Object() {
return myObj;
}
Object* return_created_Object() {
return new Object();
}
bool modify_Object( Object& obj) {
// obj = myObj; return true; both possible
return obj.modifySomething() == true;
}
};
You can only return non-local objects by reference. The destructor may have invalidated some internal pointer, or whatever.
Don't be afraid of returning values -- it's fast!
I will show you some examples:
First example, do not return local scope object, for example:
const string &dontDoThis(const string &s)
{
string local = s;
return local;
}
You can't return local by reference, because local is destroyed at the end of the body of dontDoThis.
Second example, you can return by reference:
const string &shorterString(const string &s1, const string &s2)
{
return (s1.size() < s2.size()) ? s1 : s2;
}
Here, you can return by reference both s1 and s2 because they were defined before shorterString was called.
Third example:
char &get_val(string &str, string::size_type ix)
{
return str[ix];
}
usage code as below:
string s("123456");
cout << s << endl;
char &ch = get_val(s, 0);
ch = 'A';
cout << s << endl; // A23456
get_val can return elements of s by reference because s still exists after the call.
Fourth example
class Student
{
public:
string m_name;
int age;
string &getName();
};
string &Student::getName()
{
// you can return by reference
return m_name;
}
string& Test(Student &student)
{
// we can return `m_name` by reference here because `student` still exists after the call
return stu.m_name;
}
usage example:
Student student;
student.m_name = 'jack';
string name = student.getName();
// or
string name2 = Test(student);
Fifth example:
class String
{
private:
char *str_;
public:
String &operator=(const String &str);
};
String &String::operator=(const String &str)
{
if (this == &str)
{
return *this;
}
delete [] str_;
int length = strlen(str.str_);
str_ = new char[length + 1];
strcpy(str_, str.str_);
return *this;
}
You could then use the operator= above like this:
String a;
String b;
String c = b = a;
Well, it is maybe not a really beautiful solution in the code, but it is really beautiful in the interface of your function. And it is also very efficient. It is ideal if the second is more important for you (for example, you are developing a library).
The trick is this:
A line A a = b.make(); is internally converted to a constructor of A, i.e. as if you had written A a(b.make());.
Now b.make() should result a new class, with a callback function.
This whole thing can be fine handled only by classes, without any template.
Here is my minimal example. Check only the main(), as you can see it is simple. The internals aren't.
From the viewpoint of the speed: the size of a Factory::Mediator class is only 2 pointers, which is more that 1 but not more. And this is the only object in the whole thing which is transferred by value.
#include <stdio.h>
class Factory {
public:
class Mediator;
class Result {
public:
Result() {
printf ("Factory::Result::Result()\n");
};
Result(Mediator fm) {
printf ("Factory::Result::Result(Mediator)\n");
fm.call(this);
};
};
typedef void (*MakeMethod)(Factory* factory, Result* result);
class Mediator {
private:
Factory* factory;
MakeMethod makeMethod;
public:
Mediator(Factory* factory, MakeMethod makeMethod) {
printf ("Factory::Mediator::Mediator(Factory*, MakeMethod)\n");
this->factory = factory;
this->makeMethod = makeMethod;
};
void call(Result* result) {
printf ("Factory::Mediator::call(Result*)\n");
(*makeMethod)(factory, result);
};
};
};
class A;
class B : private Factory {
private:
int v;
public:
B(int v) {
printf ("B::B()\n");
this->v = v;
};
int getV() const {
printf ("B::getV()\n");
return v;
};
static void makeCb(Factory* f, Factory::Result* a);
Factory::Mediator make() {
printf ("Factory::Mediator B::make()\n");
return Factory::Mediator(static_cast<Factory*>(this), &B::makeCb);
};
};
class A : private Factory::Result {
friend class B;
private:
int v;
public:
A() {
printf ("A::A()\n");
v = 0;
};
A(Factory::Mediator fm) : Factory::Result(fm) {
printf ("A::A(Factory::Mediator)\n");
};
int getV() const {
printf ("A::getV()\n");
return v;
};
void setV(int v) {
printf ("A::setV(%i)\n", v);
this->v = v;
};
};
void B::makeCb(Factory* f, Factory::Result* r) {
printf ("B::makeCb(Factory*, Factory::Result*)\n");
B* b = static_cast<B*>(f);
A* a = static_cast<A*>(r);
a->setV(b->getV()+1);
};
int main(int argc, char **argv) {
B b(42);
A a = b.make();
printf ("a.v = %i\n", a.getV());
return 0;
}
It isn't really good practice to return an initiated object as it does go out of scope. There are rare instances that this is the desired option. It actually can be done if the class is a referencing counting smart pointer or some other smart pointer.
How does a reference-counting smart pointer's reference counting work?