i am having trouble with my code. I am abit stumped.
I have a data member which is a pointer to a string type.
I use the constructor as a defualt initialer to this pointer, then when I call an object in the main function the intialised pointer to points to the memory address where the string is stored and prints the contents. That is what is supposed to happen, but I can't get the program to work. May somebody please tell me where I am going wrong?
#include<iostream>
#include<string>
using namespace std;
class NoName{
public:
NoName(string &sName("Alice In Wonderland") ){};
private:
string *pstring;
};
int main(){
//the constructor will be automatically called here once a object is created
// and the string "Alice in Wonderland" will appear on the screen
return 0;
}
Just simply use a std::string member and initialize it in Member initializer list:
private:
string mstring;
public:
NoName():mstring("Alice In Wonderland"){}
You could also let the constructor take in a parameter instead of hardcoding the string and let the user pass the string at run-time:
NoName(std::string str):mstring(str){}
You do not need a pointer. By using a pointer to std::string You nullify the advantages of implicit manual memory management offered by std::string.
If you really need to store a pointer for some reason, then there are some points to remember:
Pointers are initialized like new Class
Prefer to initialize class members in the member initializer list
Any time you write the word new think about where you're going to write delete. (In this case it goes in the destructor.
Rule of Three: If you need a destructor (you do, because of delete), then you also need a copy constructor and copy assignment operator.
This is one way your code could look: http://ideone.com/21yGgC
#include<iostream>
#include<string>
using std::cout; using std::endl;
using std::string;
class NoName
{
public:
NoName(string sName = "Alice In Wonderland") :
pstring(new string(sName))
{
cout << "ctor - " << *pstring << endl;
}
NoName(const NoName& rhs) :
pstring(new string(*rhs.pstring))
{
cout << "Copy ctor - " << *pstring << endl;
}
NoName& operator=(const NoName& rhs)
{
*pstring = *rhs.pstring;
cout << "Copy assignment operator - " << *pstring << endl;
return *this;
}
~NoName()
{
cout << "dtor, my name was " << *pstring << endl;
delete pstring;
}
private:
string *pstring;
};
.
int main()
{
NoName m, n("Another name");
NoName o(m);
o = n;
return 0;
}
Notice how much easier it is if you don't use the unnecessary pointer:
class Better
{
public:
Better(string sName = "Alice In Wonderland") :
m_string(sName)
{
}
private:
string m_string;
};
Because you don't need the custom destructor, you also don't need the copy constructor or copy assigment operator either. Much easier!
You're not using the constructor properly. First of all, you create this reference parameter and try to initialize it to a string object (that's asking for problems). Second, your constructor never actually does anything.
You need to call new on your pointer, dereference it and give the data pointed to a value, output the dereferenced value with std::cout and then clean the memory up with delete in the destructor (or in this case, you can do it after you use cout if you're not planning on using that string again. But do it in the destructor if you need it still).
Assuming you're doing this for a class, your textbook should tell you how to do these things.
EDIT: this is also not the default-constructor. I changed your tag to match appropriately.
Related
So, I've been exploring on how to create a dynamical array with a custom template class that I made.
#include <iostream>
#include <vector>
//HOW TO SET CLASS INTO DYNAMICAL ARRAY WITH VECTOR
//CREATE A CLASS
class User{
std::string name;
public:
User(){
}
User(std::string name){
this->name = name;
}
void set_name(std::string name){
this->name = name;
}
std::string get_name(){
return name;
}
};
int main(){
//SET A NORMAL ARRAY THAT CAN CONTAIN AN OBJECT
User user[1];
//DO WHATEVER WITH THE USER[0] TO SET EVERYTHING THAT LATER WILL BE PUT IN VECTOR
user[0].set_name("Meilianto");
std::cout << "user[0]: " << user[0].get_name() << std::endl;
//CREATE A DYNAMICAL ARRAY WHICH IS VECTOR
std::vector<User> vuser;
//PUSHBACK TO THE VECTOR AS "FIRST ELEMENT" BY PUTTING "USER[0]" AS AN ARGUMENT
vuser.push_back(user[0]);
std::cout << "vuser[0]: " << vuser[0].get_name() << std::endl;
//YOU CAN "MODIFIED" THE "USER[0]" AND ADD AGAIN AS THE "SECOND ELEMENT" OF VECTOR
user[0].set_name("Meilianto1");
vuser.push_back(user[0]);
std::cout << "vuser[1]: " << vuser[1].get_name() << std::endl;
//YOU CAN EVEN "MODIFIED" THE "FIRST ELEMENT" BY CALLING THE "METHOD" OF IT
vuser[0].set_name("Hantu");
std::cout << "vuser[0]: " << vuser[0].get_name() << std::endl;
//THE QUESTION HERE, CAN I DECLARE ARRAY TOGETHER WITH THE CONSTRUCTOR?
User user1[1]("Bebek");
//AND AFTER THAT I CAN ADD THAT OBJECT STRAIGHT AWAY TO VECTOR WITHOUT ASSIGNING ALL THE
//MEMBERS ONE BY ONE
return 0;
}
If you have read my comments in my code, what I am trying to do is maybe it will be faster if I just construct right away when I create the object instead of assigning all the members one by one that will cost more code. I imagine if in the future there will be an object with a lot of members and need to assign it one by one. It won't be efficient.
EDIT: I edit the User user[0] into User user[1], Thanks
If you're using a modern standard of C++, then you can do this
std::vector<User> vuser {
{"Meilianto1"},
{"Hantu"},
{"Bebek"}
};
Where each pair of inner brackets with a string calls User constructor, and outer pair of brackets calls std::vector<User> constructor with a sequence of Users
THE QUESTION HERE, CAN I DECLARE ARRAY TOGETHER WITH THE CONSTRUCTOR ?
User user1[1]("Bebek");
You can use list initialization for that, for arrays as well as for vectors:
User users[] { std::string("Herbert"), std::string("Anton") };
std::vector<User> vusers { std::string("Herbert"), std::string("Anton") };
CAN I ADD THAT OBJECT STRAIGHT AWAY TO VECTOR WITHOUT ASSIGNING ALL THE MEMBERS ONE BY ONE
You can initialize a vector with the elements of an previously defined array like this:
std::vector<User> v2users(std::cbegin(users), std::cend(users));
BTW: note that User user[0]; in your code defines an array without elements, i.e. of size 0, which rarely makes sense. Accessing user[0] leads to undefined behaviour
Yes, you can!
User users[]{ User{ "one" }, User{ "two" } };
// Construct vector from iterator-pair:
std::vector<User> users_vector{ std::cbegin(users), std::cend(users) };
You can use emplace_back method or push_back with temporary object to add the vector. For example;
vuser.emplace_back("Meilianto1"); // 1
vuser.push_back(User{"Meilianto1"}); // 2
The first one passes the arguments to the constructor. The second one will move the variable to vector. To be honest, there will be copy elision that's why there will be no move or copy. Just it will construct the variable.
Learning C++ and all about constructors (Copy, Move), I am wondering what the correct/smart/efficient way would be.
The following scenario:
I have a class Movie that contains title, rating and counter. Every time I instantiate an object of that class, I want that object be placed into an array (called Movies) of objects. So if I watched 3 movies, my array would contains three instances of the class Movie. Since my movie class does not contain a RAW pointer, I am wondering if there is a difference in performance whether I use copy or move to add a particular movie into my collection. I hope my idea is clear to better understand the following code. Hopefully, someone can enlighten me. Thank you,
Mingw-w64 version 8.1.0, Win10, VSCode:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
class Movie
{
private:
string movieName;
int movieRating;
int movieCounter;
public:
string getName();
Movie(string movieNameVal="None", int movieRatingVal=0);
Movie(const Movie &source);
Movie(Movie &&source);
~Movie();
};
Movie::Movie(string movieNameVal, int movieRatingVal)
: movieName(movieNameVal), movieRating(movieRatingVal) // Equivalent to movieName = movieNameVal; movieRating = movieRatingVal;
{
cout << "Constructor called" << endl;
}
// Copy constructor
Movie::Movie(const Movie &source)
: Movie(source.movieName, source.movieRating)
{
cout << "Copy constructor called" << endl;
}
// Move constructor
Movie::Movie(Movie &&source)
: movieName(source.movieName), movieRating(source.movieRating)
{
cout << "Move constructor called" << endl;
}
Movie::~Movie()
{
cout << "Destructor called" << endl;
}
int main()
{
{
vector<Movie> Movies1;
cout << "------------Movies1: Copy constructor version------------" << endl;
Movie movie1("Terminator 1", 5);
Movies1.push_back(movie1);
}
cout << endl;
cout << endl;
cout << endl;
{
vector<Movie> Movies2;
string namex = "Terminator 2";
int ratingx = 5;
cout << "------------Movies2: Move constructor version------------" << endl;
Movies2.push_back(Movie(namex, ratingx));
}
return 0;
}
You asking about the difference in performance when you append in a vector by copying or moving the object instance of your particular class.
First, you can always measure! I think the majority of time taken would go in the vector reallocating its capacity(), so when you have an idea of the number of objects that will be inserted, is always recommended to reserve() some memory.
Looking the output of your very code snippet:
------------Movies1: Copy constructor version------------
Constructor called
Constructor called
Copy constructor called
Destructor called
Destructor called
------------Movies2: Move constructor version------------
Constructor called
Move constructor called
Destructor called
Destructor called
I think I already see a winner. As said in the comments, in your particular class you may let the compiler generate the default constructors; generally the move may be more efficient than the copy (see more here).
However, consider this third possibility:
Movies3.emplace_back(namex, ratingx);
------------Movies3: emplace_back version------------
Constructor called
Destructor called
That wouldn't be so bad.
I am new to C++, and I have some questions about how the union works. This is my code :
#include <iostream>
using namespace std;
union S
{
std::string str;
int a;
~S() {}
};
int main()
{
S s {};
s.str = "hello";
std::cout << s.str << std::endl;
s.a = 3;
std::cout << s.a;
std::cout << "This is my string : " << s.str << std::endl;
}
If I write " S s" instead of " S s{}", i have a error --> use of the deleted function S::S().
if I delete this line "~S() {}", i have a error --> use of the deleted function S::~S().
In this website, https://en.cppreference.com/w/cpp/language/union,
it is said that because I have a member (string) with a non default constructor/destructor, it will delete the default constructor and the default destructor of the union S. My question is :
Why? I still don't understand why they delete the default constructor/destructor in C++.
Also, I have heard it is important to explicitly call the destructor if i want to switch the string to an integer because it will leads to the memory leak.My question is: Do I need to call the union destructor or the string destructor? In this code,if I need to call the union destructor, the destructor does nothing, so does that means my string won't be ereased?. If I need to call the string destructor, I don't know how to write the string destructor. Thank !
When i run this code, it shows me this :
hello
3
This is my string :
As I have expected, the last sentence "This is my string :" doesn't show me the string "hello" because I have overwrite "s.a = 3".
But, it seems s.str is empty. My questions is: Why does s.str is empty. Does it mean that the compiler has called automatically the destructor of my string. Thank!
I know there are alternative like boost or variant, but I still want to understand this.
If I write " S s" instead of " S s{}", i have a error --> use of the deleted function S::S().
S contains a string and this string must be constructed before it can be used. You've gotten around this with aggregate initialization which ensures the first member of the union will be correctly initialized.
Note that if a was the first member, it would be initialized rather than str and s.str = "hello"; exhibits some of that classic Undefined Behaviour action.
You could also satisfy the compiler by adding a constructor that constructed the member you wished to use as the active member. Then it doesn't matter what order. As of C++20 you can use designated initializers, S s{.str=""};, to select which member to initialize and still use aggregate initialization to avoid writing a constructor
if I delete this line "~S() {}", i have a error --> use of the deleted function S::~S().
Just as str must be constructed, you also need to have scaffolding to ensure that it can be destroyed if str is the active member when s is destroyed. This usually requires more than just a union because you need some book-keeping to track the active member. Destroying str when it is not the active member is a fatal mistake.
Also, I have heard it is important to explicitly call the destructor if i want to switch the string to an integer because it will leads to the memory leak.My question is: Do I need to call the union destructor or the string destructor? In this code,if I need to call the union destructor, the destructor does nothing, so does that means my string won't be ereased?. If I need to call the string destructor, I don't know how to write the string destructor. Thank !
Any time you stop using s as a string, before assigning to s.a or when destroying s when s is being used as a string, you need to call the string destructor to end the lifetime of str.
So
s.a = 3;
needs to become
s.str.~string();
s.a = 3;
In addition, any time you want to make str the active member, you need to make sure it is constructed.
std::cout << "This is my string : " << s.str << std::endl;
needs to become
new (&s.str) std::string("I'm Baaaaaack!");
std::cout << "This is my string : " << s.str << std::endl;
and then, because str is the active member we should destroy it before main exits.
s.str.~string();
All bundled up we get,
#include <iostream>
using namespace std;
union S
{
std::string str;
int a;
~S()
{
}
};
int main()
{
S s{};
s.str = "hello";
std::cout << s.str << std::endl;
s.str.~string();
s.a = 3;
std::cout << s.a;
new (&s.str) std::string("I'm Baaaaaack!");
std::cout << "This is my string : " << s.str << std::endl;
s.str.~string();
}
I very recently started getting into C++, my main language has always been Java.
I want to be able to pass a reference to an object in a constructor so the object constructed can use the passed object and make changes to it.
Doing some research on the subject I've come across copy constructors but I haven't quite understood if they are strictly needed for this operation and what they really accomplish in the first place.
TLDR: I want to learn how to do the equivalent of the following Java code in C++.
Java code
class Master {
private Slave slave;
Master(Slave slave) {
this.slave = slave;
}
public void doSomethingToSlave() {
slave.doSomething();
}
public void changeSlave(Slave s) {
this.slave = s;
}
}
C++ Code ??? -my attempt so far-
class Master {
public:
Master(Slave& slave);
void doSomethingToSlave();
void changeSlave(Slave& s);
private:
Slave& slave; // Is this correct? Do I need to specify that it's a reference?
}
Master::Master(Slave& slave) { // Copy constructor needed?
this->slave = slave;
}
Master::doSomethingToSlave() {
slave.doSomething();
}
Master::changeSlave(Slave& s) {
slave = s;
}
Using Pointers ?
class Master {
public:
Master(Slave* slave);
void doSomethingToSlave();
void changeSlave(Slave* s);
private:
Slave* slave;
}
Master::Master(Slave* slave) {
this->slave = slave;
}
Master::doSomethingToSlave() {
slave.doSomething(); // How do I access the object at slave*?
}
Master::changeSlave(Slave* s) {
slave = s;
}
Here's an example which I hope elucidates the behavior:
#include <iostream>
using namespace std;
class MyType {
public:
int value;
};
int main() {
// value == 1
MyType obj1{1};
// initialize a reference to refer to obj1.
MyType &ref = obj1;
// value == 2
MyType obj2{2};
// ref refers to obj1.
cout << "A. ref.value = " << ref.value << endl;
// this actually reassigns the memory in obj1
// to the memory from obj2.
ref = obj2;
cout << "B. obj1.value = " << obj1.value << endl;
// value == 3
MyType obj3{3};
// initialize a pointer to point to obj3.
MyType *ptr = &obj3;
// ptr refers to obj3.
cout << "C. ptr->value = " << ptr->value << endl;
// now we're just reassigning the pointer value.
// this is like Java reference assignment.
// ptr now points to obj2.
ptr = &obj2;
cout << "D. obj3.value = " << obj3.value << endl;
// now we're reassigning the memory at obj2 to
// the memory from obj1.
// this is what the C++ reference assignment is doing.
*ptr = obj2;
cout << "E. obj2.value = " << obj2.value << endl;
return 0;
}
The output is as follows:
A. ref.value = 1
B. obj1.value = 2
C. ptr->value = 3
D. obj3.value = 3
E. obj2.value = 2
A Java reference is actually like a C++ pointer, but Java doesn't let you do the dereference and assignment *ptr = value.
However, I agree with what others are saying that approaching C++ with the coding style of Java isn't really a good idea. Modern C++ programs don't really use raw pointers. They use smart pointers or value objects, because C++ doesn't have garbage collection. If you're passing raw pointers around, it's difficult to figure out exactly when a particular object needs to be destroyed.
In your case, I think you'd use a std::shared_ptr<Slave>.
A value object is like Slave slave;, which is a stack-allocated object if it's declared in a method body, or it's stored directly inside the memory for an object if it's declared as a member of a class or struct.
A copy constructor (ctor) is used to copy an object, i.e. to create a copy of the object of the same type, given as argument.
In your case,
Master::Master(Slave& slave)
is not a copy ctor, and a copy ctor is not required for Master.
However, Slave should have a copy ctor and an assignment operator due to
Master::changeSlave(Slave& s) {
slave = s;
}
This is because you are assigning a copy of s to the object that slave points to. This is likely not what you wanted to do. To reassign the pointer, do use a pointer (rather smart than raw ointer) and not a reference, which cannot be reassigned.
Helpful references:
For me, C++ for Java Programmers, especially the summary of differences between C++ and Java, has helped moving from Java to C++.
About cloning: Though assignment operators and regular ctors are usually used, the clone pattern is also helpful in C++. Good examples can be found in Item 25 of More Effective C++ (Virtualizing ctors and non-member functions).
Lets take the example some of the codes like the following use objects but can access their members directly without using any '.' operator
Eg-1
#include <iostream>
#include <string>
using namespace std;
int main () {
string mystr;
cout << "What's your name? ";
getline (cin, mystr);
cout << "Hello " << mystr << ".\n";
cout << "What is your favorite team? ";
getline (cin, mystr);
cout << "I like " << mystr << " too!\n";
return 0;
}
Here mystr is an object of std::string but it can access the group of characters inside it without using the '.' operator it should be
getline(cin,mystr.(member_name)); //Here member name is the name of the member which is there inside the class std::string and stores the data
But the actual working code is
getline(cin,mystr);
Second thing what is indirection
Edit 1:
Ok let me put this in a more simpler way if i have some class which has some data members and if i want to use any data member then i need to refer it from the object like
Eg-2
class reff{
public:
int a;
int b;
}
reff per;
per.a=36;
This statement tells that to access any class' members we need to refer it from the object but the same is not happening in the example of std:: string which i have mentioned above mystr is an object so it must be having some data member to store the data if i want to display the data inside a std::string object then i should mention the data member's name along with the objects name but in Eg-1 only object's name is mentioned.
The reason the call to getline(cin,mystr); does not directly specify any of the members of mystr is because the getline() function requires a string object, not one of its member variables. The actual implementation will access the individual members, but as a user of the string class, you don't need to (or want to) know those details. This concept is known as encapsulation, and allows you to seperate what a thing does (stores and allows access to a string of characters) from how it does it (pointers and length counters, static buffers, or whatever).
In your example:
class reff{
public:
int a;
int b;
};
reff per;
per.a=36;
you directly access the a member, but we could write a function which requires a reference to a reff object to set the value of its member variable:
void setValueA(reff& obj, int value)
{
obj.a = value;
}
and then use similar syntax to the getline() method on it:
setValueA(per, 36);
to achieve the same thing as per.a = 36, but with the benefits of encapsulation: if you later need to change the details of how reff stores its data (e.g. changing a and b to meaningful names), you only need to change the function implementation to use the new data members; all user code using this class will continue to work. If user code directly accessed the members, it would also need to be changed to use the new name.
Notice that setValueA() is accessing the member variables of the object it is passed; so calling it with per.a directly is not only unnecessary, but impossible:
setValueA(per.a, 36); // invalid: setValueA() requires a reff&, not an int
since the function itself tries to utilise the member a of the object it is passed, and an int does not have any members.
For the getline() call using a std::string, it has the same issue: for this function to work, it needs at the minimum:
read/write access to a pointer to the memory to store the data it reads (it may need to reallocate this if there's not enough space already allocated); and
the amount of memory pointed to the above, so it knows how much additional data it can store before it needs to allocate additional space.
So, given that getline() requires more than just a single intrinsic type in order to function, it should be clear why the parameter includes a string object rather than one of its specific member variable.
For additional examples, you should look up operator overloading, which can even let you do things like have per = 36; assign a value to per.a.
Here's a self-contained example using overloaded operators on a slightly modified version of your reff class. The comments try to explain what's going on, and should give you terms you can search for - this stuff is all pretty basic C++ and should be covered in any tutorial series.
#include <iostream>
class Reff
{
public:
int a;
float b; // changed the data type to illustrate overloading the = operator
// operator= will be called if we try to assign to a an object of this class;
// this version of the function accepts an integer value
Reff& operator= (int intval)
{
a = intval;
return *this;
}
// another operator=, this one accepting a float value as the parameter
Reff& operator= (float floatval)
{
b = floatval;
return *this;
}
};
// operator+ will be called if we try to add a value to this object;
// I'm only defining this one which accepts an int value
int operator+ (Reff const& reff, int intval)
{
return reff.a + intval;
}
// an overload of the operator<< function, which accepts a reference to
// an instance of a Reff, along with the output stream parameter.
std::ostream& operator<< (std::ostream& stream, Reff const& reff)
{
return stream << "[a:" << reff.a << " b:" << reff.b << "]";
}
int main()
{
// create an instance of our class
Reff per;
// assign the instance 42 (an integer value) - this will use the integer
// overload of the operator= we defined
per = 42;
// assign it a floating point value - this will use the float overload
// of the operator=. Note that if we didn't define a float-specific overload,
// the compiler would probably truncate the value to an integer and use our
// integer version instead - possibly with a warning, possibly silently,
// depending on your compiler settings.
per = 3.14159f;
// output the object; this will use the overload of the operator<< function
// that we created, which accepts our Reff object
std::cout << per << std::endl;
// output the result of adding 58 to our object; this will use the operator+
// overload which accepts an integer
std::cout << "per + 58 = " << (per + 58) << std::endl;
}
Here you can get output directly through
cout << "I like " << mystr << " too!\n";
because operator << is overridden in string Class.
like:
ostream& operator << (ostream& OS, MyString & S)
{
OS << S.get_string();
return OS;
}
Check whole implementation : http://www.cplusplus.com/forum/beginner/15396/