I am new to C++ and I've been learning how a program is executed. I am working on this code:
#include <iostream>
#include <string>
using namespace std;
void sayHello() {
cout << "Hello world!" << endl;
}
void greet(string name) {
cout << "Hello " << name << ", how are you?" << endl;
}
int main()
{
sayHello();
int a = 10;
string name = "Johan";
greet(name);
return 0;
}
I debugged this code in Code Blocks IDE. When it reached the return 0 statement, the yellow arrow (step into mode) returned to the string name statement and then it went to the return statement again to finish the debugging. I thought it is related to freeing memory, but why didn't it go to the int a = 10?
Is it normal? What did the debugger do? Shouldn't the debugger go to the closing bracket directly?
Thank you very much.
This is because std::string is a class with a non-default destructor, and this is your debugger's way of telling you that it's about to destroy this std::string object, by invoking its destructor. The debugger is saying, in so many words "ok, I'm doing the return statement now, and the first order of business is to destroy this std::string, so the execution jumps to the line which declared this std::string object, to let you know I'm about to execute this destructor; now, there, I've done it, now I'll resume the process of returning from this function".
A plain int doesn't have a fancy-shmancy destructor, and nothing special needs to be done, in order to make it go away.
Related
#include <iostream>
#include <string>
using namespace std;
static inline string BoolToString(bool boolean_exp) {
return boolean_exp? "True" : "False";
}
class Foo {
public:
explicit Foo(int _size) noexcept :
my_resource(new int[_size]) {
cout << "Foo obj init, at: " << this << ", my_resource at:" << my_resource <<endl;
my_resource[0] = 1234567;
}
~Foo() {
cout << "A Foo instance at: " << this << " is finalizing; ";
cout << "my_resource: " << my_resource << endl;
delete[] my_resource;
my_resource = nullptr;
}
public:
int *my_resource = nullptr;
};
void function_foo(Foo f) {
cout << "function_foo() invoked" << endl;
}
int main(int argc, char *argv[]) {
Foo foo(20);
function_foo(foo); // I think, foo's copy should released after function_foo() return-ed, my_resource should be nullptr;
cout << "Is foo.my_resource released?: " << BoolToString(foo.my_resource == nullptr) << endl;
cout << (*foo.my_resource) << endl;
return 0;
}
Obviously, after the function_foo function is called in the main function, a shallow copy of foo is passed to function_foo as an argument, and that shallow copy should be destructured after function_foo is finished. After the function has finished running, the my_resource field in foo (declared in the main function) is still can be parsed and get value 1234567I would like to know why this is?
My idea is that although the memory resource pointed to by my_resource is freed when the temporary object is destructured, this memory resource is not reclaimed or not overwritten, so it can still be accessed in the wrong way.
Did the compiler did what it shouldn't have done?
By the way, I use clang++ as compiler and the development environment is windows.
compile: clang++ file.cxx -o file.exe
run: ./file
Result:
Foo obj init, at: 0x61fdd8, my_resource at:0x1f1e90
function_foo() invoked
A Foo instance at: 0x61fdd0 is finalizing; my_resource: 0x1f1e90
is foo.my_resource released?: False
1234567
A Foo instance at: 0x61fdd8 is finalizing; my_resource: 0x1f1e90
After the function has finished running, the my_resource field in foo (declared in the main function) is still can be parsed and get value 1234567I would like to know why this is?
It is undefined behavior, so it may work if you are unlucky.
In typical C++ implementations, this has a good chance of not crashing, because the allocation is smaller than a page and allocators are not required to return the memory back to the operating system. This means your process still has the ability to read that address.
In addition, the compiler didn't decide to use the address for something else, so it just so happens that the value is still there.
The memory resource is released, but that doesn't mean that it's gone! It's just marked as "free memory" and the next time something in your program tries to allocate memory it might be given that piece of memory. So, yeah... it's still there... for now... but you shouldn't rely on it, because you cannot predict what is going to happen to it in the future.
C++ doesn't bother to somehow "lock access" or even just "erase" the released memory because that would only take up CPU cycles for no tangible benefit. After you've released the memory, you're not supposed to touch it anyway.
Firstly please have a look at some simple codes that my questions derived from.
#include <iostream>
#include <string>
using namespace std;
string get_something()
{
cout << "output something";
return " and return something";
}
void print_something()
{
cout << "print something";
}
int main()
{
cout << get_something(); // will work
cout << print_something(); // will NOT work
return 0;
}
The only different thing I notice between get_something() and print_something() is that one is a return type and one isn't. As you can see I have added comments indicating that which one will work and not work.
However, I am really not sure what is happening behind the scene that makes it one possible and the other not possible.
I am not even sure how I should go about and search for this kind of question too.. so here I am asking a question.
Please enlighten me..
edit:
I am confused that how it is possible to do cout after cout..
both of the functions do that but one of them works and the other doesn't.
This seems to be a very common misunderstanding among beginners. Printing something via cout is not the same as returning a value from a function. Thats completely orthogonal things.
You can write:
std::string returned_value = get_something();
std::cout << returned_value;
But you cannot write:
??? returned_value = print_something();
std::cout << returned_value;
because print_something() does not return anything! void denotes the absence of a type. You cannot have an object of type void.
On the other hand, when you call a function, you can use the returned value (above), or you can ignore it, so this is correct code:
print_something(); // prints something
get_something(); // also print something and returned value is ignored
Note that the function get_something should get a better name, because it is not just "getting" a value. How about print_and_return_something()?
PS:
What I am really confused about is that, how is it possible to do a cout after a cout? Am I just missing what cout actually does?
Not sure If I understand, but I will try... std::cout is an object of type std::ostream. It has an operator<< that you can call, similar to calling methods of other objects. The following two are identical and just use different syntax:
std::cout.operator<<( "Hello World");
std::cout << "Hello World";
When you call print_something() then first the function is executed, then the return value is returned to the caller and execution continues with the caller. This:
std::cout << get_something();
is more or less the same as (well, its a crude simplification, but should be ok here):
// inside get_something
std::cout << "output something";
// return value
std::string result{"output something"};
// now execution continues in caller
std::cout << result;
Calling cout after cout is no different from calling some other function. Suppose you have a function print() that prints something then you can write
std::string print_and_return() {
std::string x{"Hello World"};
print(x);
return x;
}
The caller can do
std::string x = print_and_return(); // <- this already calls print()
print(x); // now we call it again
This is more or less the same as yours, just that I used some hypothetical print() instead of std::cout::operator<<.
Both your functions have a return type. It's just that one of them has a void return type.
The std::ostream class does not have an overload for << that takes a void type. This is sensible - what would be written to the stream in that case?
(cout is an instance of std::ostream that typically writes itself to the standard output which is normally the shell you're using to launch the program.)
Because print_something() has nothing to return, and cout want something to write to the console (the return value it is expecting). Therefore, it will give error.
get_something(), on the other hand, has something to return. So after executing it's rest of line (except return statement) it return the string, which gets printed by cout
get_something() returns something (what seems to be accepted by cout), so cout will receive the returned thing and will work.
On the other hand, print_something() returns nothing (because its return type is void), so cout cannot receive anything to print and won't work.
cout is a stream object.and we use << (insertion operator) to insert value like String,float,Int etc to it which will be displayed in output Screen.Since print_something() is not returning any value so nothing is inserted in stream ,That's why it is not working.
I recommend you to read about Streams in c++ ..
# include <iostream>
# include <string>
using std::string;
using std::cout;
using std::endl;
string func() {
string abc = "some string";
return abc;
}
void func1(string s) {
cout << "I got this: " << s << endl;
}
int main() {
func1(func());
}
This gives:
$ ./a.out
I got this: some string
How/why does this code work ? I wonder because abc went out of scope and got destroyed as soon as the call to func() completed. So a copy of abc cannot be/should not be available in variable s in function func1 Is this understanding correct ?
The return value is copied from the local variable, effectively creating a new string object.
However, RVO (returned value optimization) should eliminate this step.
Try single stepping your code in a debugger. You should see the std::string copy constructor called for the return line. Be sure to compile with debug enabled and optimizers off.
Your code is essentially asking:
"Call func1, and in order for func1 to work I have to receive a string which we can use by calling the copy constructor on that string. The parameter for func1 we want to come from the return value of func (which we know has to be a string since its explicitly defined".
abc goes out of scope only after the copy constructor is called on the return value of func() which passes the value of the string. In theory you could have written it passed by reference or constant reference:
void func1(string& s) {
cout << "I got this: " << s << endl;
}
Which allows func1 to directly access the string in memory through a pointer (and also change it, if your code was meant to.)
void func1(string const& s) {
cout << "I got this: " << s << endl;
}
Which provides a constant reference to the string from func(). This ensures that you get a pointer to the data and that you won't change its contents. Typically passing data by constant reference (const&) is desirable because it's very fast and keeps your code from accidentally changing data that it shouldn't.
You really only need to pass by value if you're going to manipulate the data once you pass it to the new function, saving you the resources of creating another new container to handle the manipulation:
void func1(string s) {
s += " some extra stuff to add to the end of the string"; //append some new data
cout << "I got this: " << s << endl;
}
I have this piece of code (something I threw together trying to isolate a weird error in a chess program I'm trying to write):
#include <vector>
#include <iostream>
class piece{
public:
piece() : COLOUR('C'){}
const char COLOUR;
};
std::vector<piece*> makeEmptyLine(){
std::vector<piece*> emptyLine;
piece null;
emptyLine.push_back(&null);
return emptyLine;
}
int main(){
std::vector<piece*> emptyLine = makeEmptyLine();
std::cout << (*emptyLine[0]).COLOUR;
std::cout << (*emptyLine[0]).COLOUR;
std::cout << (*emptyLine[0]).COLOUR;
return 0;
}
And the output is C\367\367
The first std::cout << (*emptyLine[0]).COLOUR; always prints "C" (the expected result). But when it's used again, it outputs that backslash and three digits which change depending on how many times I use cout in the program.
You have an undefined behaviour because you use the address of a local variable null which is destroyed once your function makeEmptyLine() returns.
Does your compiler complain when you try to compile it with the highest warning level?
I want to build a program that support multi-language but if I included the language selection code into the main function it will be messy, so I make another function called language then I wrote the code below:
#include <iostream>
int language() {
std::cout << "1.English\n2.中文";
}
int main() {
std::cout << language();
}
Then my Code::Blocks IDE gave me a warning:
*warning: no return statement in function returning non-void [-Wreturn-type]|*
I still can compile the code using MinGW via command prompt, but the compiled program gave me the output below:
1.English
2.中文4683872
Then I add return 0; after the std::cout << "1.English\n2.中文"; but it display 0 instead of 4683872 above.
I am still learning C++ and I have no idea what happened to my code, and is there is any ways to remove those numbers?
In your program, you print your string first and after you print the return value of the function... That's why you have a number after the string.
Just try :
// I don't think your language function need to return something
// So make it void
void language() {
std::cout << "1.English\n2.中文";
}
int main() {
language(); // Here no need to print the value returned by the language function
return 0; // Main return an int, 0 is for success
}
Just to explain a bit more :
The fact that your language() function return an int value and that you are not returning anything leads to Undefined behaviour. That's why you get a value like 4683872. And it is also why you have a warning at the compilation.
You have two problems in your code: The first is that you declare language as returning an int but then not actually returning anything. This is what the warning is about. The other problem is based on the first one, and that you actually use this "returned value" even though there is none, which leads to undefined behavior.
You can solve it in two ways: Either return a valid value from the function, or declare it as returning void and don't use the function in an expression.
You've got to get your return values sorted out! You want the language function to return an output stream, since you're feeding it's output into std::out in main. You might as well pass in an output stream into language so you could reuse it with a different output stream to std::out. Also, main has to return an int. Standard practice is to return 0 unless there's an error.
#include <iostream>
std::ostream& language(std::ostream& os) {
os << "1.English\n2.中文";
return os;
}
int main() {
std::cout << language(std::cout) << std::endl;
return 0;
}
If you want the user to select a language then your code needs to be more like this:
#include <iostream>
int language() {
int choice;
std::cout << "1.English\n2.中文"; // print menu of language choices
std::cin >> choice; // get selection from user
// NB: real code would have error checking here to make sure that `choice` is valid
return choice; // return selection
}
int main() {
std::cout << language();
}
The std::cout << language(); is printing an integer for you since language() returns an int. If you don't want anything to print after your text, then remove the std::cout << in your main.
#include <iostream>
void language() {
std::cout << "1.English\n2.中文";
}
int main() {
language();
return 0;
}