C++ Using naked, instead of smart pointers - c++

Consider the following code.
#include <iostream>
#include <vector>
#include <memory>
int main() {
std::vector<std::string> vec;
for(int i =0;i<10;i++){
vec.push_back("adsf");
}
std::string* myPoint = &vec[1];
*myPoint = "this works";
std::shared_ptr<std::string> str_ptr = std::make_shared<std::string>(vec[0]);
str_ptr->push_back('this does not push_back to the end of the string stored in at vec[0]');
for(int i =0;i<10;i++){
std::cout << vec[i] << std::endl; //does not print the new value set by str_ptr
}
return 0;
}
What I want here is to update a value in vec through a pointer. As I've understood smart pointers are no good for this task. Is using a naked pointer here, an acceptable alternative?

make_shared does not mean "make this already-existing thing be shared".
It means "make a new shared thing with the following constructor arguments".
You're dynamically allocating a new string that copies vec[0] (i.e. using the copy constructor).
If you want vec[0] to be a shared_ptr<string>, then you need to make it one from the start.

Related

How to make unordered_map<string*, V> hash by value instead of reference?

I have the following
The two equivalent strings bar and bartest do not map to the same value in unordered_map. How can I make this happen?
Of course they don't map to the same value, const string* is a pointer type and since you call new string twice, you end up with two separate objects that don't have memory identity (the pointers are not equal).
What's worse, you leak both of them at the end of your program.
What's (arguably) worse still, owning raw pointers and naked new calls are considered harmful in modern c++.
Luckily it's all fixed with unordered_map<string, int> - no pointers required whatsoever.
Your C++ is in fact "Java-- + C".
Remove all those silly pointers.
All you need is unordered_map<string,int> and use plain values instead of heap-allocated "news"
just do
#include <unordered_map>
#inclide <string>
#include <iostream>
int main()
{
unordered_map<string,int> mymap;
mymap["bar"] = 5;
mymap["bartest"] = 10;
std::cout << mymap["bar"] << ' ' << mymap["bartest"] << '\n';
return 0;
}

How to initialized Pointer of Vector c++?

The following code is not working :
vector< vector<int> > *te = new vector< vector<int> >();
(*te)[0].push_back(10);
cout << (*te)[0][0];
How should I initialize it ?
I do not see a sense in dynamic allocation of the vector nevertheless a correct syntax can look like
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int> > *pv = new std::vector<std::vector<int> >;
pv->push_back( std::vector<int>( 1, 10 ) );
std::cout << ( *pv )[0][0] << std::endl;
delete pv;
}
The output is
10
std::vector<std::vector<int>>* te = new std::vector<std::vector<int>>();
This line isn't you're problem. However, it does beg the question "Why are you dynamically allocating a std::vector?"
(*te)[0].push_back(10);
This line is your problem. You're accessing the 0th index of te but it's empty (i.e., doing this invokes undefined behavior). You need to add something to it first: te->push_back(std::vector<int>());.
Example Code
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>>* te = new std::vector<std::vector<int>>();
// Add an empty `vector` to `te`
te->push_back(std::vector<int>());
// Add `10` to the first `vector` in `te` and print it
(*te)[0].push_back(10);
std::cout << (*te)[0][0];
delete te;
return 0;
}
Note: You should also be in the habit of using smart pointers and not worry about manually newing and deleting the memory (e.g., std::unique_ptr pointer and std::make_unique).

Pass vector by reference to constructor of class

I have a class called test with which I want to associate a large vector with in the order of million elements. I have tried doing this by passing a pointer to the constructor:
#include <iostream>
#include <vector>
using namespace std;
class test{
public:
vector<double>* oneVector;
test(vector<double>* v){
oneVector = v;
}
int nElem(){return oneVector->size();}
};
int main(){
vector<double> v(1000000);
cout << v.size() << endl;
vector<double>* ptr;
test t(ptr);
cout << t.nElem()<< endl;
return 0;
}
However, this results in a Segmentation Fault:11, precisely when I try to do t.nElem(). What could be the problem?
This is C++, don't work with raw pointers if you don't absolutely need to. If the goal is to take ownership of a std::vector without copying, and you can use C++11, make your constructor accept an r-value reference, and give it sole ownership of the std::vector that you're done populating with std::move, which means only vector's internal pointers get copied around, not the data, avoiding the copy (and leaving the original vector an empty shell):
class test{
public:
vector<double> oneVector;
test(vector<double>&& v):oneVector(std::move(v)){
}
int nElem(){return oneVector.size();}
};
int main(){
vector<double> v(1000000);
cout << v.size() << endl;
test t(std::move(v));
cout << t.nElem()<< endl;
return 0;
}
If you really want a pointer to a vector "somewhere else", make sure to actually assign ptr = &v; in your original code. Or new the vector and manage the lifetime across test and main with std::shared_ptr. Take your pick.
ptr is not initialized. What you "want" to do is:
test t(&v);
However, I think you'd be better suited with references here (it's in the title of your question after all!). Using references avoids unnecessary syntax (like -> over .) which just unnecessarily hinder the reading of the code as written.
class test
{
std::vector<double>& oneVector;
public:
test(vector<double>& v) : oneVector(v) {}
size_t nElem() const { return oneVector.size(); }
};
ptr is an uninitialized pointer. This unpredictable value gets copied to t.oneVector. Dereferencing it is undefined behavior.
You need your pointer to actually point at a valid vector.
You forgot to give your pointer the desired value, namely the address of the vector:
vector<double>* ptr = &v;
// ^^^^^^
In your code, ptr remains uninitialized, and your program has undefined behaviour.

C++ Use of smart pointers inside STL containers

What is the benefit of using smart pointers inside STL containers ( vectors, maps etc... ) knowing that these containers manages already the memory ?
Example:
std::vector<std::unique_ptr<int>>
instead of
std::vector<int*>
If the objects are pointers it is not enough to manage the memory the pointers occupy. You also need to manage what the pointers point to. It is a good idea to store the objects pointed to instead of the pointers (in case of your example std::vector<int> would be appropriate), however, in case you have polymorphic objects that is not possible.
You can use it when you need to hold an array of references to objects. That way I can sort an array of references without actually moving the objects around in memory.
#include <algorithm>
#include <iostream>
#include <memory>
#include <vector>
int main()
{
std::shared_ptr<int> foo(new int(3));
std::shared_ptr<int> baz(new int(5));
std::vector<std::shared_ptr<int> > bar;
bar.push_back(baz);
bar.push_back(foo);
std::sort(bar.begin(), bar.end(), [](std::shared_ptr<int> a, std::shared_ptr<int> b)
{
return *a < *b;
});
for(int i = 0; i < bar.size(); ++i)
std::cout << *bar[i] << std::endl;
return 0;
}
Prints:
3
5

ostream, copy function printing string address, instead of string contents

This prints the address for my string, but not its' contents,
#include <memory>
#include <string>
#include <list>
#include <iostream>
#include <iterator>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
unique_ptr<list<shared_ptr<string>>> upList (new list<shared_ptr<string>>);
shared_ptr<string> spNation (new string ("India"));
upList->push_back (spNation);
copy (upList->begin(), upList->end(), ostream_iterator<shared_ptr<string>> (cout, "\n "));
return 0;
}
My questions are:
What ostream_iterator<shared_ptr<string>> is taking shared_ptr or strings as its' prime object.
How to print actual string contents (i.e. India) using this approach.
Is this approach is preferable over traditional for loop to print all node contents.
What ostream_iterator<shared_ptr<string>> is taking shared_ptr or strings as its' prime object.
You've instantiated ostream_iterator for shared_ptr<string>, so that is what it will attempt to output.
How to print actual string contents (i.e. India) using this approach.
If you really want to use shared pointers for some reason, then you can't use copy since that won't undo the extra level of indirection. Either use a plain loop, or get rid of the unnecessary indirection:
list<string> list;
list.push_back("India");
copy(list.begin(), list.end(), ostream_iterator<string>(cout, "\n "));
Of course, it doesn't look as exciting without all the arrows, templates, new-expressions and pseudohungarian warts, but anyone trying to maintain the code won't thank you for adding such embellishments.
Is this approach is preferable over traditional for loop to print all node contents
It's preferable when it makes the code simpler. When it doesn't, it isn't.
Firstly: why you use shared_ptr<string> instead of string here? You shouln't do this.
1)
shared_ptr<string>
2) Use std::for_each with lambda (or range-based for loop)
for_each(upList->begin(), upList->end(), [](const shared_ptr<string>& p)
{
cout << *p << endl;
});
or
for (const auto& p : upList)
{
std::cout << *p << std::endl;
}