This is the code.
int main()
{
unique_ptr <int> p {nullptr};
int val = 100;
p = &val; // Not working - compilation error
p = move(&val); // Not working - compilation error
cout << *p;
return 0;
}
What is the correct way?
Only dynamically allocated objects should be assigned to unique_ptrs, because the unique_ptr may try to delete the object.
As for the actual question, the reset() function of unique_ptr is used to reassign the pointer.
With unique_ptr::reset:
p.reset(&val);
Of course in this particular case this will result in undefined behavior when p goes out of scope and it tries to delete the int, but that's another matter.
Related
Does anyone could explain me the reason of this coding recommendation ?
Since C++11, please initialize data members on declaration (not
necessary on constructor) :
class Limit
{
public:
Limit() = default;
private:
int32_t quantity = 0;
double price = 0.0;
};
Someone thinks (correctly) that this way the variable is always initialised. Which is a good thing if it is initialised with a meaningful value and bad if the value is not meaningful. For example a person’s year of birth is a number from say 1890 to 2021. Initialising it to 0 isn’t useful and can only prevent the compiler from warning you.
So do this if you have a value that is always a useful initialisation value. I wouldn’t do it for anything that is likely to be overwritten in a constructor or shortly after.
I found this answer from CppCoreGuidelines C-48 :
C.48: Prefer in-class initializers to member initializers in constructors for constant initializers
Reason
Makes it explicit that the same value is expected to be used in all constructors. Avoids repetition. Avoids maintenance problems. It leads to the shortest and most efficient code.
Example, bad
class X { // BAD
int i;
string s;
int j;
public:
X() :i{666}, s{"qqq"} { } // j is uninitialized
X(int ii) :i{ii} {} // s is "" and j is uninitialized
// ...
};
How would a maintainer know whether j was deliberately uninitialized (probably a bad idea anyway) and whether it was intentional to give s the default value "" in one case and qqq in another (almost certainly a bug)? The problem with j (forgetting to initialize a member) often happens when a new member is added to an existing class.
Example
class X2 {
int i {666};
string s {"qqq"};
int j {0};
public:
X2() = default; // all members are initialized to their defaults
X2(int ii) :i{ii} {} // s and j initialized to their defaults
// ...
};
Alternative: We can get part of the benefits from default arguments to constructors, and that is not uncommon in older code. However, that is less explicit, causes more arguments to be passed, and is repetitive when there is more than one constructor:
class X3 { // BAD: inexplicit, argument passing overhead
int i;
string s;
int j;
public:
X3(int ii = 666, const string& ss = "qqq", int jj = 0)
:i{ii}, s{ss}, j{jj} { } // all members are initialized to their defaults
// ...
};
Enforcement
(Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default construction).
(Simple) Default arguments to constructors suggest an in-class initializer might be more appropriate.
There is also the guideline C-45 that explains it.
I am trying to std::bind class functions in combination of std::unique_ptr and I have a lot of trouble getting it to work
First I have two classes
class simpleClass{
public:
simpleClass(int x){
this->simpleNumber = x;
}
int simpleNumber;
simpleClass(const simpleClass &toBeClone){
this->simpleNumber = toBeClone.simpleNumber;
}
simpleClass clone(){
simpleClass *cloned = new simpleClass(*this);
return *cloned;
}
};
class className{
public:
className(doube input){
this->someVariable = input;
}
void someFunction(std::vector<double> x, double c, std::unique_ptr<simpleClass> &inputClass, std::vector<double> &output){
std::vector<double> tempOutput;
for(int i = 0; i<x.size(); i++){
tempOutput.push_back(x[i] + c * this->someVariable + inputClass->simpleNumber);
}
output = tempOutput;
}
double someVariable;
className(const className &toBeClone){
this->someVariable = toBeClone.someVariable;
}
className clone(){
className *cloned = new className(*this);
return *cloned;
}
};
They are both some standard class, but I also implement a clone function to duplicate an initialized class. While cloning, I need to ensure that the original class and the cloned class points to different address. So I use std::unique_ptr to ensure this.
The is the main function, which also shows how I "clone"
int main(){
className testSubject(5);
std::vector<std::unique_ptr<className>> lotsOfTestSubject;
simpleClass easyClass(1);
std::vector<std::unique_ptr<simpleClass>> manyEasyClass;
for(int i = 0; i<10; i++){
std::unique_ptr<className> tempClass(new className(testSubject.clone()))
lotsOfTestSubject.push_back(std::move(tempClass));
std::unique_ptr<simpleClass> tempEasyClass(new simpleClass(easyClass.clone()))
manyEasyClass.push_back(std::move(tempEasyClass));
}
std::vector<std::vector<<double>> X; //already loaded with numbers
double C = 2;
std::vector<std::vector<<double>> OUT;
for(int i = 0; i<10; i++){
std::vector<double> tempOUT;
lotsOfTestSubject[i]->someFunction(X[i], C, manyEasyClass[i], tempOUT);
OUT.push_back(tempOUT);
//Here if I want to bind
/*
std::bind(&className::someFunction, lotsOfTestSubject[i], X[i], C, manyEasyClass[i], tempOUT);
*/
}
return 0;
}
The reason why I "clone" is because both simpleClass and className takes a lot of time for construction in my implementation, and I need a lot of them. And Since many of them will be initialized with the same parameters, I figured this is the easiest way to do so.
The code above works, but I am trying to improve the speed of the loop. The following line is where most of the computation takes place.
lotsOfTestSubject[i]->someFunction(X[i], C, manyEasyClass[i], tempOUT);
So I am attempting to use threads to delegate the work , and as far as I know, I need to std::bind first. So I tried
std::bind(&className::someFunction, lotsOfTestSubject[i], X[i], C, manyEasyClass[i], tempOUT);
But the compiler prints error like this
/usr/include/c++/5/tuple|206| recursively required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 1ul; _Head = std::vector<double>; _Tail = {double, std::unique_ptr<simpleClass, std::default_delete<simpleClass> >, std::unique_ptr<simpleClass, std::default_delete<simpleClass> >, std::vector<double>}]’|
/usr/include/c++/5/tuple|108|error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = className; _Dp = std::default_delete<className>]’|
I have no idea what this means as I just started self teaching c++. Any feedback and guidance is much appreciated.
I am using c++11 and g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Update
Thanks #rafix07, tried your solution and it works fine. but then I tried to do
auto theBinded = std::bind(&className::someFunction, &lotsOfTestSubject[i],
X[i], C, std::ref(manyEasyClass[i]), tempOUT);
std::thread testThread(theBinded);
and eventually want to testThread.join()
But the compiler says
error: pointer to member type ‘void (className::)(std::vector<double>, double, std::unique_ptr<simpleClass>&, std::vector<double>&)’ incompatible with object type ‘std::unique_ptr<className>’|
#kmdreko Thanks for you point out! I haven't notice memory leak yet, but I will fix it. Do I just use this?
std::unique_ptr<className> tempClass = new className(testSubject);
EDIT
If you want to call someFunction on instance stored in lotsOfTestSubject you need to pass pointer to className object on which this method will be called, so the line below
std::bind(&className::someFunction, lotsOfTestSubject[i]
should be replaced by:
auto theBinded = std::bind(&className::someFunction, lotsOfTestSubject[i].get(),
^^^
Second change is to use std::ref to pass original instance of unique_ptr of manyEasyClass instead of its copy. std::bind always copies or moved its arguments (see reference), but unique_ptr is non-copyable, that is why compilation failed.
So fixed line looks:
auto theBinded = std::bind(&className::someFunction, lotsOfTestSubject[i].get(),
X[i], C, std::ref(manyEasyClass[i]), std::ref(tempOUT));
tempOUT also must be passed by std::ref because you want to modify this vector by call operator() on functor created by bind.
LIVE DEMO
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.
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
As the unmanaged C++ is feel free to locate to different object.
Such as the pointer to an array
int pt[50];
int* pointer = pt;
We can directly use *pointer to get the first value of the element in the array.
Thus, we can also use *(pointer++) in order to point to the second element.
However, if it is possible to directly use ^(pointer+5) to get the sixth element of the array?
The example is as follow.
array<int>^ pt = gcnew array<int>(50);
int^ pointer = pt;
How can I use the pointer as a medium to access different element in the array?
here is a slightly different approach that may be of use ...
It uses interior pointer arithmetic (to traverse an array).
Hope this helps.
using namespace System;
ref class Buf
{
// ...
};
int main()
{
array<Buf^>^ array_of_buf = gcnew array<Buf^>(10);
// Create a Buf object for each array position
for each (Buf^ bref in array_of_buf)
{
bref = gcnew Buf();
}
// create an interior pointer to elements of the array
interior_ptr<Buf^> ptr_buf;
// loop over the array with the interior pointer
// using pointer arithmetic on the interior pointer
for (ptr_buf = &array_of_buf[0]; ptr_buf <= &array_of_buf[9]; ptr_buf++)
{
// dereference the interior pointer with *
Buf^ buf = *ptr_buf;
// use the Buf class
}
}
reference: C++/CLi the visual c++ language for .net (pg 99)
here is another example from: https://msdn.microsoft.com/en-us/library/y0fh545k.aspx
// interior_ptr.cpp
// compile with: /clr
using namespace System;
ref class MyClass {
public:
int data;
};
int main() {
MyClass ^ h_MyClass = gcnew MyClass;
h_MyClass->data = 1;
Console::WriteLine(h_MyClass->data);
interior_ptr<int> p = &(h_MyClass->data);
*p = 2;
Console::WriteLine(h_MyClass->data);
// alternatively
interior_ptr<MyClass ^> p2 = &h_MyClass;
(*p2)->data = 3;
Console::WriteLine((*p2)->data);
}