C++ Issue with scope? [duplicate] - c++

This question already has answers here:
What is a dangling pointer?
(7 answers)
Closed 12 days ago.
I am trying to swap a pointer to point to the address of a new class instance created inside a method, but once back to main, the reference is lost, is this because of scope? Could someone please care to explain? Does c/c++ have reference counting?
#include <iostream>
class MyClass {
public:
int myNum;
std::string myString;
MyClass(int my_num, std::string my_string)
{
myNum = my_num;
myString = my_string;
}
};
void SwapRef(MyClass **p)
{
MyClass b(99, "test");
*p = &b;
}
int main(int argc, char* argv[])
{
MyClass a(1, "main");
MyClass* aPtr = (MyClass*)0;
aPtr = &a;
std::cout << "myNum is: " << aPtr->myNum << " myString is: " << aPtr->myString << "\n";
SwapRef(&aPtr);
std::cout << "myNum is: " << aPtr->myNum << " myString is: " << aPtr->myString << "\n";
#ifdef _WIN32 || _WIN64
system("pause");
#endif
}
OUTPUT:
myNum is: 1 myString is: main
myNum is: -858993460 myString is:

This function
void SwapRef(MyClass **p)
{
MyClass b(99, "test");
*p = &b;
}
is wrong. The object b having automatic storage duration will not be alive after exiting the function. So the pointer aPtr assigned in the function with the address of the local object using the expression statement
*p = &b;
will be invalid after exiting the function.
Dereferencing such a pointer invokes undefined behavior.
Instead you could write
**p = b;
using the generated by the compiler the default copy assignment operator.
The function could be correct if the object declared within the function would have static storage duration like
void SwapRef(MyClass **p)
{
static MyClass b(99, "test");
*p = &b;
}
In this case it will be alive after exiting the function.
Pay attention to that you should include header <string>
#include <string>
because it is not necessary that the header <iostream> includes the header <string>.

Related

Why C++ erase params of object accessed by reference from other object also accessed by reference? [duplicate]

This question already has answers here:
C++ dangling reference strange behaviour
(5 answers)
What is a dangling reference? [duplicate]
(1 answer)
Closed last month.
I am relatively new in C++ and didn't expect the behavior shown in code below.
Can you, please, advise why is it happening and how to fix it?
DataWrapper.h
#pragma once
class DataWrapper
{
public:
int myVal;
DataWrapper();
};
DataWrapper.cpp
#include "DataWrapper.h"
DataWrapper::DataWrapper()
{
myVal = 1;
}
DataCaller.h
#pragma once
#include "DataWrapper.h"
class DataCaller
{
public:
DataWrapper* dwRef;
DataCaller();
void PrintData();
};
DataCaller.cpp
#include "DataCaller.h"
#include <iostream>
DataCaller::DataCaller()
{
dwRef = &DataWrapper();
int extractedVal = dwRef->myVal;
int dwAddr = (int)dwRef;
std::cout << "Val In DataCaller Constructor: "<< extractedVal << " dwAddr: " << dwAddr << std::endl;
}
void DataCaller::PrintData()
{
int extractedVal = dwRef->myVal;
int dwAddr = (int)dwRef;
std::cout << "Val In DataCaller PrintData: " << extractedVal << " dwAddr: " << dwAddr << std::endl;
}
Main.cpp
#include <post-processing/DataCaller.h>
int main(int argc, char* argv[])
{
DataCaller dc = DataCaller();
dc.PrintData();
return 0;
}
So I fill the value in DataWrapper constructor , in DataCaller constructor I create DataWrapper pointer, then print DataWrapper pointer's value.
I also print this value in regular method of DataCaller class.
When I print it in constructor, it is equal to 1, as written in DataWrapper constructor, but when I print it in DataCaller method - the value is set to rubbish.
At the same time "dwAddr" is the same in both cases.
Here is an example of my output:
Val In DataCaller Constructor: 1 dwAddr: 2035349268
Val In DataCaller PrintData: -858993460 dwAddr: 2035349268
Can you, please, advise why is it happening and how to fix it?
As explained by #RichartCritten in the comment, the object created via DataWrapper() is destroyed at the end of the expression
dwRef = &DataWrapper();
which results in undefined behaviour.
If you want to keep the object, one alternative is to make dwRef a non-pointer member variable.
class DataCaller
{
public:
DataWrapper dwRef;
DataCaller();
void PrintData();
};
...
DataCaller::DataCaller()
: dwRef(/* constructor parameters could be listed here */)
{
...
}
Alternatively allocate the object via new; It's preferrable to have a smart pointer manage the calls to new and delete though:
...
#include <memory>
...
class DataCaller
{
public:
std::unique_ptr<DataWrapper> dwRef;
DataCaller();
void PrintData();
};
...
DataCaller::DataCaller()
{
dwRef = std::make_unique<DataWrapper>(/* constructor parameters could be listed here */);
...
}
Note: To print the address via a std::ostream, it's preferrable to cast to void*; this results in a implementation defined output of the address, but usually it's an output format that works well for addresses:
// assuming the second alternative I presented is used
std::cout << "Val In DataCaller PrintData: " << extractedVal << " dwAddr: " << static_cast<void*>(dwRef.get()) << std::endl;

What is the difference when a dereferenced variable type in c++ has '&' or does not have '&'? [duplicate]

This question already has answers here:
What does '&' do in a C++ declaration?
(7 answers)
how does the ampersand(&) sign work in c++? [duplicate]
(3 answers)
Closed 1 year ago.
In the following lines of code, if I remove the '&' from the line ('***'), there would not be any change in the functionality apparently. Is there any reason to keep it as is or could it be useful in any case?
Would you elaborate a little bit about the differences?
Thanks.
#include <iostream>
class Entity
{
public:
void Print() const
{
std::cout << "Hello" << std::endl;
}
Entity()
{
std::cout << "Constructed!" << std::endl;
}
};
int main()
{
Entity e;
Entity* ptr = &e;
// ***
Entity& entity = *ptr;
entity.Print();
std::cin.get();
}
You can see the difference if you actually put some state into your class and try to change it. If you copy by reference the change in the original is also seen in the copy. If you copy by value (without the & ) then a change in the original is not seen in the copy.
#include <iostream>
#include <string>
class Entity
{
public:
std::string m_message;
Entity(std::string msg ):m_message(msg){}
void Print() const
{
std::cout << m_message << std::endl;
}
};
int main()
{
Entity e("cat");
Entity* ptr = &e;
// assign by reference is a bit like taking a pointer in
// that it refers back to the original object but you
// don't have to use '*' to dereference it. Also it is
// not able to be null.
Entity& byRef = *ptr;
// assign by value creates a new object with no link to
// the previous object
Entity byVal = *ptr;
byRef.Print();
byVal.Print();
std::cout << "========" << std::endl;
e.m_message="dog";
byRef.Print();
byVal.Print();
}
which outputs
cat
cat
========
dog
cat
See https://godbolt.org/z/r4qehWxY3

Pointer address assignment in c++ [duplicate]

This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 1 year ago.
i'm code beginner
#include <bits/stdc++.h>
using namespace std;
void init(int* arr){
arr = new int[10];
cout << arr << endl;
}
int main(int argc, char* argv[]){
int *arr;
init(arr);
cout << arr << endl;
}
this is a simple code.
My question is that why arr's address in init function and arr's address in main function is different?
My think is that i gave arr's address to init function and in init function, arr is assigned a new address through 'new int[10]'
So, arr's address in init function and in main will be same.
but this code doesn't work as i think.....
Can you tell me why?
Step back a little and think about how arguments are passed into functions.
void foo(int x) {
}
int main() {
int x;
foo(x);
}
Here the x in main() is actually passed by value to foo() which means a copy of x is created when passing to foo().
With the same logic, if you think of int * as another variable type
using intPtr = int*; //a sort of typedef
void foo(intPtr x) {
}
int main() {
intPtr x;
foo(x);
}
a copy of x is again created. This is what is happening in your program. For what you expect, you need to pass in the variable by reference
using intPtr = int*;
void foo(intPtr& x) {
}
int main() {
intPtr x;
foo(x);
}
Adapting the same to your program:
#include <iostream>
void init(int*& arr){
arr = new int[10];
std::cout << arr << '\n';
}
int main(int argc, char* argv[]){
int *arr;
init(arr);
std::cout << arr << '\n';
delete(arr);
}
There's another way with pointers that is using a pointer to a pointer (**)
#include <iostream>
void init(int** parr){
*parr = new int[10];
std::cout << *parr << '\n';
}
int main(int argc, char* argv[]){
int *arr;
init(&arr);
std::cout << arr << '\n';
delete(arr);
}
where the address of arr (&arr) is passed into the function. Inside the function, the contents of parr is modified (which is arr in this case).

Deleting this pointer from constructor [duplicate]

This question already has answers here:
c++ delete pointer issue, can still access data [closed]
(6 answers)
Closed 3 years ago.
I tried deleting this pointer from constructor, and afterwards when i access private variable through a member function, the variable is fetched correctly.
If I try to delete this again(in constructor or func()), my program crashes. That means this pointer is deleted fine in constructor.
class B
{
int a;
public:
B()
{
std::cout << this;
std::cout << "\nConstructor\n";
delete this;
a = 5;
std::cout << "\n" << this;
}
~B()
{
std::cout << "Destructor\n";
}
void func()
{
std::cout << "\n" << a << " Func\n";
}
};
int main(int argc, char* argv[])
{
B *b = new B();
b->func();
return 0;
}
But calling func() prints correct output. I expected some error due to deleted this. Why the implicit argument of func() is not updated when deleted?
delete this is allowed and just fine. Accessing any members of the class after deleting it however is not allowed and is undefined behavior. Your code appearing to work is one form that UB can take.

std::cout changing the variable value

I was coding my function is properly returning a pointer to a reference.
I found that although the function was returning what it was suppose to do, however, std::cout was modifying the results.
Am I doing anything wrong here?
How to rectify this behaviour?
Please refer the following code snippet,
#include "stdafx.h"
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass(int x_):m_Index(x_){}
int m_Index;
};
void myfunction(int *&currentIndex, MyClass obj)
{
currentIndex = &obj.m_Index;
}
int _tmain(int argc, _TCHAR* argv[])
{
MyClass obj(5);
int *Index = NULL;
myfunction(Index, obj);
int curr_Index = *Index;
cout << "Index = " << curr_Index << std::endl; // This works fine.
cout << "Index = " << *Index << std::endl; // This modifies *Index
return 0;
}
void myfunction(int *&currentIndex, MyClass obj)
{
currentIndex = &obj.m_Index;
}
Invokes undefined behavior because obj is only valid for the life of the function call. You keep a pointer to it (or one of it's members) which you use AFTER it has gone out of scope.
You can solve either by pointing to something that doesn't go out of scope (see #songyuanyao's answer). In this case it isn't clear why you need pointers. myfunction could just return the index.
The obj parameter is passed by value, so a copy is made that will be destroyed when the function exits. currentIndex is being set to point to an invalid address, and dereferencing it is undefined behavior. It might work well, or it might not work, anything is possible.
One solution is to make obj be passed by reference instead of by value:
void myfunction(int *&currentIndex, MyClass& obj)
{
currentIndex = &obj.m_Index;
}