Call a method as a R-Value - c++

I am reading a book about the new features of C++11, 14 and 17. In the chapter about move-semantics the author uses the following class as an example:
class DataObject {
public:
DataObject(int n, int v): data_(new int[n]), size_(n) {
std::fill(data_, data_ + size_, v);
}
virtual ~DataObject() {
delete[] data_;
}
... //copy constructor, assignment operator
private:
int* data_;
int size_;
}
Now, he introduces the overloaded method getData() which returns data_ as a
L- or a R-Value:
//For L-Value
int* getData() const& {
int* result(new int[size_]);
copy(data_, data_ + size_, result);
return result;
}
//For R-Value
int* getData() && {
return data_;
data_ = nullptr;
size_ = 0;
}
The following examples are shown afterwards:
DataObject do(4, 10);
int* data1 = do.getData();
int* data2 = DataObject(5, 20).getData();
I have a problem with the R-Value getData() method; it does not make sense to me. We return data_ and then we set data_ to nullptr... but the function was left already with return data_. How can data_ = nullptr and size_ = 0 can ever be executed? And even if they would be executed, the destructor would try to delete nullptr when DataObject(5,20) gets out of scope.
Question:
Is there an error or am I misunderstanding something? How the two lines can be executed after we leave the function?

Your premise is wrong (emphasize mine):
The introduces the overloaded method getData() which returns data_ as
a L- or a R-Value
The & and && refer to the object on which you invoke the method (just as the const does in that place) not the return type. And thats what the example is demonstrating:
DataObject do(4, 10);
int* data1 = do.getData();
// ^ this is a l-value
int* data2 = DataObject(5, 20).getData();
// ^ this is a r-value
Now to your actual question:
We return data_ and then we set data_ to nullptr... but the function
was left already with return data_
You are completely right, and that code is nonsense. There is no way the statements after the return will ever be executed.
PS: Usually I avoid spreading my opinions on books and the like, but in this case I have to tell you that it is a really bad example and you should stay away from that book.

Related

Over-using mutable to enhance security?

Suppose I have a class that has an array of pointers, and I have a method that dereferences a pointer and returns it as a reference. I want to allow the method caller to call non-const methods of the object the pointer is pointing to, but also want to protect myself from the caller changing what the pointer is pointing to. If I return a const reference, I have to mark many of the pointer object's methods as const, and hence many of its class member variables as mutable.
Is this bad practice? If so, how do I get around this?
Is there performance penalty for over-using mutable?
Example:
#include <iostream>
#include <array>
#include <memory>
class Counter
{
public:
Counter();
void hit() const;
void reset();
unsigned count() const;
private:
mutable unsigned count_;
};
Counter::Counter() : count_(0) {}
void Counter::hit() const { ++count_; }
void Counter::reset() { count_ = 0; }
unsigned Counter::count() const { return count_; }
class CircularArray
{
public:
CircularArray();
const Counter& next() const;
private:
mutable unsigned i_;
std::array<std::unique_ptr<Counter>, 3> arr_;
};
CircularArray::CircularArray() : i_(2)
{
arr_[0] = std::unique_ptr<Counter>(new Counter);
arr_[1] = std::unique_ptr<Counter>(new Counter);
arr_[2] = std::unique_ptr<Counter>(new Counter);
}
const Counter& CircularArray::next() const { return *arr_[(i_ = (i_ + 1) % 3)]; }
int main()
{
CircularArray circular;
const Counter* p;
p = &circular.next();
p->hit();
p->hit();
Counter c;
//*p = c; // <-- Want to prevent this
}
To extend what I was saying, there is no point in abusing mutable for this. If this is all you want to prevent:
*p = /* ... */;
then it can be done much more easily by deleting the assignment operator of Counter:
class Counter
{
void operator=(const Counter&) = delete;
// ...
};
Remember that the assignment operator does not affect the identity of the object: it doesn't change its address. Semantically, an assignment involving of modifying this object to replicate the state of another object. In fact, even if you forbid me from using the assignment operator somehow, I could still do this:
// a very inefficient way of performing `*p = c`
p->reset();
while (p->count() != c.count())
p->hit();
This achieves the exact same result as performing an assignment, albeit very clumsily and inefficiently.
Performing an assignment is no different than calling a non-const member function that accepts a single argument of type const Counter&. Hypothetically, you could redefine the assignment operator to do absolutely nothing at all if you wanted to (it would be a bad idea though).

C++ Explain "one liner" constructor that overloads member function Iterator(int i = 0) : i(i) { };

I have a question about what this contractor is actually doing. I found it online and it works for my purpose, but I wish to understand its notation.
class Iterator {
int i;
public:
Iterator(int i = 0) : i(i) {};
friend class SinglyLinkedList<Element>;
Node* _current;
Iterator(SinglyLinkedList& list) {
this->list = list;
reset();
}
void reset() {
_current = list._head;
}
void next(){
if(!done()) {
_current = _current->_next;
}
}
bool done(){
bool done = false;
if(_current->_next == nullptr) {
done = true;
}
return done;
}
private:
SinglyLinkedList list;
};
This is a member function that proves it works.
unsigned long print(Element e, const Iterator& index) {
cout << index.i << "\n";
return 0;
When const Iterator& index = 2. The function outputs 2.
If you ignore the part about Element e, the basic idea is that I can use Iterator(SinglyLinkedList& list) and Iterator(int i = 0), both. And you can access the integer attribution by using index.i?
Any general insight is also appreciated.
The constructor
Iterator(int i = 0) : i(i) {}
lets you construct an instance of an iterator in three ways:
You can use this constructor without passing arguments (in which case zero is assumed)
You can call this constructor explicitly, passing it a single int argument, or
You can call this constructor implicitly, passing an int instead of it.
Here is the first way:
Iterator one;
Here is the second way:
Iterator two(123);
Here is the third way:
Iterator three = 321;
Back to your code, when you write this
const Iterator& index = 2;
the compiler creates a temporary object, initializes it using the implicit invocation of your constructor, and sets the reference of this temporary object into index. This is similar to the third kind of invocation of the constructor (i.e. the implicit one) but the target is a hidden, temporary object. The compiler is allowed to use a temporary here, because the index is declared const; it wouldn't compile without it.
dasblinkenlight's answer
explains the different ways this can be used, but I want to talk about what's actually going on here.
The line is Iterator(int i = 0) : i(i) {}; Let's break down all the pieces.
Iterator(int i=0) does three things:
Announces that this is a constructor for the Iterator class
Announces that this constructor takes a single int argument
Provides a default value for the single argument. In other words, the constructor calls Iterator() and Iterator(0) will have the same result
: i(i) is an initializer list. It assigns the member variable i (That's the first i) to the value of the parameter i (The i in brackets).
{}; is the body of the constructor. Nothing else is happening here, so it's been left empty.
A more verbose way of writing the same thing would be the following:
Iterator(){
i = 0;
}
Iterator(int index){
i = index;
}
That block and the line you've provided will have essentially the same result in most cases, although I don't know enough about the intricacies C++ to know if the above will work for some of the interesting cases you have (Like const Iterator& index = 2)

Providing correct move semantics

I am currently trying to figure out how to do move semantics correctly with an object which contains a pointer to allocated memory. I have a big datastructure, which contains an internal raw pointer to the actual storage (for efficiency reasons). Now I added a move constructor and move operator=(). In these methods I am std::move()ing the pointer to the new structure. However I am not sure what to do with the pointer from the other structure.
Here is a simple example of what I am doing:
class big_and_complicated {
// lots of complicated code
};
class structure {
public:
structure() :
m_data( new big_and_complicated() )
{}
structure( structure && rhs ) :
m_data( std::move( rhs.m_data ) )
{
// Maybe do something to rhs here?
}
~structure()
{
delete m_data;
}
private:
big_and_complicated * m_data;
}
int main() {
structure s1;
structure s2( std::move( s1 ) );
return 0;
}
Now from what I understand, after the std::move( s1 ) to s2 the only thing that is safe to do on s1 ist to call its constructor. However as far as I can see, this would lead to deleting the pointer contained within s1 in the destructor, rendering s2 useless as well. So I am guessing I have to do something to render the destructor safe when std::move()ing the pointer. As far as I can see the safest thing to do here, is to set it to 0 in the moved object, since this would turn the delete into a no-op later on. Is this reasoning correct so far? Or is std::move() actually smart enough to null out the pointer for me, rendering its usage safe? So far I am seeing no crashes in the actual test-suite, but I have not made sure the move-constructor is actually called.
"Moving" a pointer is no different than copying one and does not set the moved-from value to null ('moving' is in quotes here because std::move does not move anything really, it just changes the value category of the argument). Just copy rhs's pointer then set it to nullptr:
struct structure
{
structure()
: m_data{new big_and_complicated{}}
{ }
structure(structure&& rhs)
: m_data{rhs.m_data}
{
rhs.m_data = nullptr;
}
structure& operator =(structure&& rhs)
{
if (this != &rhs)
{
delete m_data;
m_data = rhs.m_data;
rhs.m_data = nullptr;
}
return *this;
}
~structure()
{
delete m_data;
}
private:
big_and_complicated* m_data;
structure(structure const&) = delete; // for exposition only
structure& operator =(structure const&) = delete; // for exposition only
}
You could also simplify this by using std::exchange:
structure(structure&& rhs)
: m_data{ std::exchange(rhs.m_data, nullptr) }
{ }
structure& operator=(structure&& rhs)
{
if (this != &rhs)
{
delete m_data;
m_data = std::exchange(rhs.m_data, nullptr);
}
return *this;
}
Better yet, use std::unique_ptr<big_and_complicated> instead of big_and_complicated* and you don't need to define any of this yourself:
#include <memory>
struct structure
{
structure()
: m_data{new big_and_complicated{}}
{ }
private:
std::unique_ptr<big_and_complicated> m_data;
}
Lastly, unless you actually want structure to remain non-copyable, you're better off just implementing proper move semantics inside of big_and_complicated and having structure hold a big_and_complicated object directly.

Implementing Smart Pointer - storing template class in vector

I'm having trouble storing instances of my smart pointer into a container. Here is the code for the pointer.
#include "std_lib_facilities.h"
template <class T>
class counted_ptr{
private:
T* pointer;
int* count;
public:
counted_ptr(T* p = 0, int* c = new int(1)) : pointer(p), count(c) {} // default constructor
explicit counted_ptr(const counted_ptr& p) : pointer(p.pointer), count(p.count) { ++*count; } // copy constructor
~counted_ptr()
{
--*count;
if(!*count) {
delete pointer;
delete count;
}
}
counted_ptr& operator=(const counted_ptr& p) // copy assignment
{
pointer = p.pointer;
count = p.count;
++*count;
return *this;
}
T* operator->() const{ return pointer; }
T& operator*() const { return *pointer; }
int& operator[](int index) { return pointer[index]; }
int Get_count() const { return *count; } // public accessor for count
};
int main()
{
counted_ptr<double>one;
counted_ptr<double>two(one);
one = new double(5);
vector<counted_ptr<double> >test;
}
In int main(), the vector<counted_ptr<double> > line does compile. When I first tried it with just vector<counted_ptr<double> > it didn't compile (probably because it was lacking parameters.) However, when I try to use push_back such as
test.push_back(one);
I get a compiler error that opens up vector.tcc with the specific error saying that
no matching function for call to `counted_ptr<double>::counted_ptr(const counted_ptr<double>&)'|
I'm guessing that push_back can't find a counted_ptr, but I'm really not sure. Any
help is appreciated, thanks.
Edit: However, this works. test[0] = one; I guess the semantics of push_back are what is restricting it.
You may want to try this:
test.push_back(counted_ptr<double>(one));
You copy constructor is explicit which means that the compiler won't implicitly invoke it.
Personally, I would make the raw pointer constructor explicit and the copy ctor not explicit. That would be closer to usual behavior.
EDIT: I also recommend that you implement a swap method. It makes assignment absolutely trivial. You end up with something like this:
counted_ptr &operator=(const counted_ptr &rhs) {
counted_ptr(rhs).swap(*this);
return *this;
}
This also has the benefit of all of the accounting happening in constructors/destructors which is a lot simpler to manage :-).
Your assignment operator is wrong.
What happened to the object it was pointing at?
What happens if you are assigning to yourself or the same internal object?
counted_ptr& operator=(const counted_ptr& p) // copy assignment
{
if (&p != this)
{
--*count;
if ((*count) == 0) // Much more readable than !*count
{
delete pointer;
delete count;
}
pointer = p.pointer;
count = p.count;
++*count;
}
return *this;
}
Note: Writing your own smart pointer is not a good idea.
They are not as trivial to write as you think.
Note: This is the first thing I spotted. There could be more, and I am not sure this is 100% correct.
In fact I would change the assignment operator to use copy/swap idium.
counted_ptr& operator=(const counted_ptr& p) // copy assignment
{
counted_ptr<T> tmp(p); // increment counter on p
swap(tmp.pointer, pointer);
swap(tmp.count count);
return *this;
// tmp goes out of scope and thus the
// destructor gets called and what was in this
// object is now destroyed correctly.
}
// It may even be worth writing your own swap operator.
// Make sure you declare it as no-throw and grantee it.

Is there C++ lazy pointer?

I need a shared_ptr like object, but which automatically creates a real object when I try to access its members.
For example, I have:
class Box
{
public:
unsigned int width;
unsigned int height;
Box(): width(50), height(100){}
};
std::vector< lazy<Box> > boxes;
boxes.resize(100);
// at this point boxes contain no any real Box object.
// But when I try to access box number 50, for example,
// it will be created.
std::cout << boxes[49].width;
// now vector contains one real box and 99 lazy boxes.
Is there some implementation, or I should to write my own?
It's very little effort to roll your own.
template<typename T>
class lazy {
public:
lazy() : child(0) {}
~lazy() { delete child; }
T &operator*() {
if (!child) child = new T;
return *child;
}
// might dereference NULL pointer if unset...
// but if this is const, what else can be done?
const T &operator*() const { return *child; }
T *operator->() { return &**this; }
const T *operator->() const { return &**this; }
private:
T *child;
};
// ...
cout << boxes[49]->width;
Using boost::optional, you can have such a thing:
// 100 lazy BigStuffs
std::vector< boost::optional<BigStuff> > v(100);
v[49] = some_big_stuff;
Will construct 100 lazy's and assign one real some_big_stuff to v[49]. boost::optional will use no heap memory, but use placement-new to create objects in a stack-allocated buffer. I would create a wrapper around boost::optional like this:
template<typename T>
struct LazyPtr {
T& operator*() { if(!opt) opt = T(); return *opt; }
T const& operator*() const { return *opt; }
T* operator->() { if(!opt) opt = T(); return &*opt; }
T const* operator->() const { return &*opt; }
private:
boost::optional<T> opt;
};
This now uses boost::optional for doing stuffs. It ought to support in-place construction like this one (example on op*):
T& operator*() { if(!opt) opt = boost::in_place(); return *opt; }
Which would not require any copy-ing. However, the current boost-manual does not include that assignment operator overload. The source does, however. I'm not sure whether this is just a defect in the manual or whether its documentation is intentionally left out. So i would use the safer way using a copy assignment using T().
I've never heard of such a thing, but then again there are lots of things I've never heard of. How would the "lazy pointer" put useful data into the instances of the underlying class?
Are you sure that a sparse matrix isn't what you're really looking for?
So far as I know, there's no existing implementation of this sort of thing. It wouldn't be hard to create one though.