shared_ptr scope basic understanding - c++11

Hi I am new to C++11 concepts. I have declared two shared pointer with difference scope. I am assigning local scope to one step higher scope shared_ptr. I am trying to print the same. Its not causing any problem. Of course i do agree our normal pointer also have the same property. But that might end up with dangling pointer. Here I just want to know whether sPtr2 pointing to invalid pointer or else its proper.
#include <iostream>
#include <memory>
using namespace std;
struct MyStruct_t
{
int a;
int b;
};
int main() {
shared_ptr<MyStruct_t> sPtr2;
if(1)
{
shared_ptr<MyStruct_t> sPtr1 (new MyStruct_t);
sPtr1->a = 5;
sPtr1->b = 10;
sPtr2 = sPtr1;
cout<<"sPtr1->a : "<<sPtr1->a<<" b value : "<<sPtr1->b<<endl;
cout<<"sPtr1 address is : "<<sPtr1<<endl;
}
cout<<"sPtr2->a : "<<sPtr2->a<<" b value : "<<sPtr2->b<<endl;
cout<<"sPtr2 Address is : "<<sPtr2<<endl;
return 0;
}

Related

How do I update the value of void** in other function, and save it to another?

If I have a code for example like this:
#include <iostream>
using namespace std;
void swap(void** a) {
int tmp = 5;
void* b = &tmp;
a = &b;
}
int main()
{
int x=11;
void* y=&x;
void** z=&y;
swap(z);
void* a = *z;
cout << *(int*)a << endl;
return 0;
}
The code above prints 11, but I want to update the value of z (its address) to point to a place so I can print 5 (I mean update it). What should I do so that when I send z to the function and get back to main I can receive 5 instead of 11.
I'm just not that good with pointers.
EDIT: I must send to swap an argument with void**
You can't update the value of a void** (i.e. what it points to) by passing it to a function that takes a void**. That only allows to modify the pointed-to memory, not what address the pointer you pass to the function points to.
To update what it points to, the parameter should be a void**& or a void***.
Regardless of what solution you choose, the code you posted is extremely error prone and a hell to maintain. You should totally avoid it.
Also, note that &tmp becomes invalid as long as you exit the function, because the local variable tmp gets destroyed.

Default constructor setting random value

I'm writing a simple class for atoms objects. Here's what I've written so far:
#include <random>
class Atom {
int mSpin;
public:
Atom();
Atom(int);
Atom(const Atom&);
~Atom() {}
Atom& operator= (const Atom &atom);
};
And the .cpp file:
include "Atom.h"
Atom::Atom() {
}
Atom::Atom(int spin) : mSpin(spin) {}
Atom::Atom(const Atom& copy) : mSpin(copy.mSpin) {}
/* OPERATORS */
Atom& Atom::operator= (const Atom &copy) {
mSpin = copy.mSpin;
return *this;
}
I want to make the default constructor such that when I'm creating an object, mSpin will be randomly set as 1 or -1. I understand how to do it with rand() but rand() is not very good and I'd like to use . I'm kind of confused by the use of , even after reading the documentation and other answers on here.
Usually I'd do something like this:
#include <random>
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0,1);
int random_number = dis(gen);
but I'm not sure how to use it inside a class. I tried placing it inside the default constructor but I think it's wrong because it would seed each time I create an atom?
Hope the question is clear.
You should make the random device and generator static members of the Atom class. This way, like global variables, they are initialized only once for the duration of your program.
class Atom {
// declaration
static std::random_device rd;
static std::mt13397 gen;
...
};
// definition - this must be in Atom.cpp
std::random_device Atom::rd;
std::mt13397 Atom::gen(Atom::rd());
You can delegate to a function in the cpp file:
namespace {
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dis(0,1);
}
int spin() {
return dis(gen) == 0 ? -1 : 1;
}
Delete your implementation of the default CTOR.
And to follow the rule 'initialise all variables' change Atom.hpp:
int spin(); // Return -1 or 1, randomly
class Atom {
int mSpin = spin();
public:
Atom() = default;
...
};
Then, in your cpp file, delete your Atom default CTOR implementation and move 'spin' function definition out of the anonymous namespace.

Directly assigning to a std::vector after reserving does not throw error but does not increase vector size

Let's create a helper class to assist visualizing the issue:
class C
{
int ID = 0;
public:
C(const int newID)
{
ID = newID;
}
int getID()
{
return ID;
}
};
Suppose you create an empty std::vector<C> and then reserve it to hold 10 elements:
std::vector<C> pack;
pack.reserve(10);
printf("pack has %i\n", pack.size()); //will print '0'
Now, you assign a new instance of C into index 4 of the vector:
pack[4] = C(57);
printf("%i\n", pack[4].getID()); //will print '57'
printf("pack has %i\n", pack.size()); //will still print '0'
I found two things to be weird here:
1) shouldn't the assignment make the compiler (Visual Studio 2015, Release Mode) throw an error even in Release mode?
2) since it does not and the element is in fact stored in position 4, shouldn't the vector then have size = 1 instead of zero?
Undefined behavior is still undefined. If we make this a vector of objects, you would see the unexpected behavior more clearly.
#include <iostream>
#include <vector>
struct Foo {
int data_ = 3;
};
int main() {
std::vector<Foo> foos;
foos.reserve(10);
std::cout << foos[4].data_; // This probably doesn't output 3.
}
Here, we can see that because we haven't actually allocated the object yet, the constructor hasn't run.
Another example, since you're using space that the vector hasn't actually started allocating to you, if the vector needed to reallocate it's backing memory, the value that you wrote wouldn't be copied.
#include <iostream>
#include <vector>
int main() {
std::vector<int> foos;
foos.reserve(10);
foos[4] = 100;
foos.reserve(10000000);
std::cout << foos[4]; // Probably doesn't print 100.
}
Short answers:
1) There is no reason to throw an exception since operator[] is not supposed to verify the position you have passed. It might do so in Debug mode, but for sure not in Release (otherwise performance would suffer). In Release mode compiler trusts you that code you provide is error-proof and does everything to make your code fast.
Returns a reference to the element at specified location pos. No
bounds checking is performed.
http://en.cppreference.com/w/cpp/container/vector/operator_at
2) You simply accessed memory you don't own yet (reserve is not resize), anything you do on it is undefined behavior. But, you have never added an element into vector and it has no idea you even modified its buffer. And as #Bill have shown, the vector is allowed to change its buffer without copying your local change.
EDIT:
Also, you can get exception due to boundary checking if you use vector::at function.
That is: pack.at(4) = C(57); throws exception
Example:
https://ideone.com/sXnPzT

How to use C++11 std::is_member_object_pointer in type_traits?

struct A { int x; };
int main() {
int A::* pt = &A::x;
return 0;
}
what does int A::* mean exactly? I have never seen C++ syntax like this.
Just like other traits, you specify the template argument and use the value member.
std::is_member_object_pointer<decltype(pa) >::value
what does int A::* mean exactly?
That is a type declaration of a member object pointer to an int member of the class A.

copy constructor does initialize primitive data types

#include <iostream>
using namespace std;
class Foo
{
public:
int a;
};
int main()
{
Foo f;
Foo f1(f);
cout<<f.a;
return 0;
}
Here f.a prints garbage value but when we add f1.a then both f.a and f1.a is initialized with 0.
#include <iostream>
using namespace std;
class Foo
{
public:
int a;
};
int main()
{
Foo f;
Foo f1(f);
cout<<f.a<<f.b;
return 0;
}
Please help me to understand what is the reason behind this.
Uninitialized variables have indeterminate values, i.e. whatever happened to be in that memory. 0 is one of possible indeterminate values, as well as any other value.
Copy c-tor does not initialize primitive data types as long as you don't explicitly declare it.
Value of uninitialized variable is determined by RAM space value which belongs to this variable, so it could be anything. But it's more likely that this ram was set to 0 (after computer restart probably).

Resources