Copying an object in C++ - c++

I would like to know if copying an object in the following manner is acceptable vis-a-vis copying the individual elements.
#include <iostream>
using namespace std;
class abc{
public:
abc(int a = 10, int b = 5);
abc(const abc &obj, int b = 10);
int ret_x() { return x; }
int ret_y() { return y; }
private:
int x;
int y;
};
abc::abc(int a, int b)
: x(a),
y(b)
{
}
abc::abc(const abc &obj, int b)
{
if (this != &obj) {
*this = obj; -----> Copying the object
}
y = b;
}
int main()
{
abc a1;
cout << "A1 values: " << a1.ret_x() << "\t" << a1.ret_y() << endl;
abc a2(a1, 20);
cout << "A2 values: " << a2.ret_x() << "\t" << a2.ret_y() << endl;
return 0;
}
Edit:
Use case:
The issue is that object a1 is auto-generated and hence any newly introduced members in the class could not be updated. I could provide a member function to update the new members, sure, but wanted to explore this option.
The code works fine, but is the method correct?
Thanks!

As chris noted already in the comments, you are creating a completely new object. How would you want to get this passed into the constructor? Well, actually, you could perhaps via placement new:
abc a;
abc* b = new(&a)abc(a);
But this is a such an exotic case that I would not consider it, I even dare to claim someone using advanced stuff such as placement new should know what he is doing... So leave out the if-check.
In your special case, it seems OK, as no data exists that might require deep copying. Be aware, though, that you are assigning the member b twice. Not really critical with int, but on larger objects (std::string, std::vector, ...) which do deep copies this gets more and more questionable.
With C++11, though, I would prefer constructor delegation:
abc::abc(const abc& obj, int b)
: abc(obj) // copying here
{
y = b;
}
This does not solve, however, the double assignment problem. To be honest, this might not always be a true problem, in many cases the compiler might optimise the first assignment away (especially in the int case of our example). But on more complex data types (possibly already std::string), I wouldn't feel comfortable relying on the compiler detecting obsolete assignment...
Be aware that you might get into trouble if you have resources managed internally:
struct abc
{
int* array;
abc() : array(new int[7]) { }
~abc()
{
delete[] array;
}
}
Not providing an appropriate assignment operator or copy constructor – depending on the implementation variant, yours (assignment) or mine (constructor delegation) – doing the necessary deep copy will result in multiple deletion of the same data (undefined behaviour!). Following the rule of three (or more recently, rule of five), you most probably will need both anyway. You might consider the copy and swap idiom idiom then.
Finally a trick to avoid double assignment:
abc(abc const& other)
: abc(other, other.y)
{ }
abc(abc const& other, int y)
: x(other.x), y(y)
{ }

Related

How to make a data member const after but not during construction?

Without relying on const_cast, how can one make a C++ data member const after but not during construction when there is an expensive-to-compute intermediate value that is needed to calculate multiple data members?
The following minimal, complete, verifiable example further explains the question and its reason. To avoid wasting your time, I recommend that you begin by reading the example's two comments.
#include <iostream>
namespace {
constexpr int initializer {3};
constexpr int ka {10};
constexpr int kb {25};
class T {
private:
int value;
const int a_;
const int b_;
public:
T(int n);
inline int operator()() const { return value; }
inline int a() const { return a_; }
inline int b() const { return b_; }
int &operator--();
};
T::T(const int n): value {n - 1}, a_ {0}, b_ {0}
{
// The integer expensive
// + is to be computed only once and,
// + after the T object has been constructed,
// is not to be stored.
// These requirements must be met without reliance
// on the compiler's optimizer.
const int expensive {n*n*n - 1};
const_cast<int &>(a_) = ka*expensive;
const_cast<int &>(b_) = kb*expensive;
}
int &T::operator--()
{
--value;
// To alter a_ or b_ is forbidden. Therefore, the compiler
// must abort compilation if the next line is uncommented.
//--a_; --b_;
return value;
}
}
int main()
{
T t(initializer);
std::cout << "before decrement, t() == " << t() << "\n";
--t;
std::cout << "after decrement, t() == " << t() << "\n";
std::cout << "t.a() == " << t.a() << "\n";
std::cout << "t.b() == " << t.b() << "\n";
return 0;
}
Output:
before decrement, t() == 2
after decrement, t() == 1
t.a() == 260
t.b() == 650
(I am aware of this previous, beginner's question, but it treats an elementary case. Please see my comments in the code above. My trouble is that I have an expensive initialization I do not wish to perform twice, whose intermediate result I do not wish to store; whereas I still wish the compiler to protect my constant data members once construction is complete. I realize that some C++ programmers avoid constant data members on principle but this is a matter of style. I am not asking how to avoid constant data members; I am asking how to implement them in such a case as mine without resort to const_cast and without wasting memory, execution time, or runtime battery charge.)
FOLLOW-UP
After reading the several answers and experimenting on my PC, I believe that I have taken the wrong approach and, therefore, asked the wrong question. Though C++ does afford const data members, their use tends to run contrary to normal data paradigms. What is a const data member of a variable object, after all? It isn't really constant in the usual sense, is it, for one can overwrite it by using the = operator on its parent object. It is awkward. It does not suit its intended purpose.
#Homer512's comment illustrates the trouble with my approach:
Don't overstress yourself into making members const when it is inconvenient. If anything, it can lead to inefficient code generation, e.g. by making move-construction fall back to copy constructions.
The right way to prevent inadvertent modification to data members that should not change is apparently, simply to provide no interface to change them—and if it is necessary to protect the data members from the class's own member functions, why, #Some programmer dude's answer shows how to do this.
I now doubt that it is possible to handle const data members smoothly in C++. The const is protecting the wrong thing in this case.
Something along these lines perhaps:
class T {
private:
T(int n, int expensive)
: value{n-1}, a_{ka*expensive}, b_{kb*expensive} {}
public:
T(int n) : T(n, n*n*n - 1) {}
};
One possible way could be to put a and b in a second structure, which does the expensive calculation, and then have a constant member of this structure.
Perhaps something like this:
class T {
struct constants {
int a;
int b;
constants(int n) {
const int expensive = ... something involving n...;
a = ka * expensive;
b = kb * expensive;
}
};
constants const c_;
public:
T(int n)
: c_{ n }
{
}
};
With that said, why make a_ and b_ constant in the first place, if you control the class T and its implementation?
If you want to inhibit possible modifications from other developers that might work on the T class, then add plenty of documentation and comments about the values not being allowed to be modified. Then if someone modifies the values of a_ or b_ anyway, then it's their fault for making possibly breaking changes. Good code-review practices and proper version control handling should then be used to point out and possibly blame wrongdoers.
Before describing the answer, I'd first suggest you to re-think your interface. If there's an expensive operation, why don't you let the caller be aware of it and allow them to cache the result? Usually the design forms around the calculations and abstractions that are worth keeping as a state; if it's expensive and reusable, it's definitely worth keeping.
Therefore, I'd suggest to put this to the public interface:
struct ExpensiveResult
{
int expensive;
ExpensiveResult(int n)
: expensive(n*n*n - 1)
{}
};
class T
{
private:
const int a;
const int b;
T(const ExpensiveResult& e)
: a(ka * e.expensive)
, b(kb * e.expensive)
{}
};
Note that ExpensiveResult can be directly constructed from int n (ctor is not explicit), therefore call syntax is similar when you don't cache it; but, caller might, at any time, start storing the result of the expensive calculation.
It's pretty easy to modify the const ints in your object as a result of a significant change in c++20. The library function construct_at and destroy_at have been provided to simplify this. For your class, destroy_at is superfluous since the class contains no members that use dynamic memory like vector, etc. I've made a small modification, added a constructor taking just an int. Also defined an operator= which allows the objects to be manipulated in containers. You can also use construct_at to decrement a_ and b_ in your operator-- method. Here's the code:
#include <iostream>
#include <memory>
namespace {
constexpr int initializer{ 3 };
constexpr int ka{ 10 };
constexpr int kb{ 25 };
class T {
private:
int value;
const int a_{};
const int b_{};
public:
T(int n);
T(int n, int a, int b);
T(const T&) = default;
inline int operator()() const { return value; }
inline int a() const { return a_; }
inline int b() const { return b_; }
int& operator--();
T& operator=(const T& arg) { std::construct_at(this, arg); return *this; };
};
T::T(const int n, const int a, const int b) : value{ n - 1 }, a_{ a }, b_{ b } {}
T::T(const int n) : value{ n - 1 }
{
// The integer expensive
// + is to be computed only once and,
// + after the T object has been constructed,
// is not to be stored.
// These requirements must be met without reliance
// on the compiler's optimizer.
const int expensive{ n * n * n - 1 };
std::construct_at(this, n, ka*expensive, kb*expensive);
}
int& T::operator--()
{
// implement decrements
//--a_; --b_;
const int a_1 = a_ - 1;
const int b_1 = b_ - 1;
std::construct_at(this, value, a_1, b_1);
return value;
}
}
int main()
{
T t(initializer);
std::cout << "before decrement, t() == " << t() << "\n";
--t;
std::cout << "after decrement, t() == " << t() << "\n";
std::cout << "t.a() == " << t.a() << "\n";
std::cout << "t.b() == " << t.b() << "\n";
return 0;
}
Output:
before decrement, t() == 2
after decrement, t() == 1
t.a() == 259
t.b() == 649

how to overload << operator in c++ to use repeatedly?

Sorry for the not clear title.
Recently I started to learn C++ and I don't know how to overload operator << to make it repeatable.
Here's an example code.
class Foo{
private:
int* a;
int idx = 0;
public:
Foo(){a = new int[100];
void operator<< (int a) {arr[idx++] = a;}
What << does is basically class get integer number as an operand and save it into arr.(Ignore overflow case here)
For example, a << 100 will add 100 into array.
What I want to do is make << operator can be repeatedly used inline like a << 100 << 200
How should I fix above code to allow this function?
Thanks in advance :)
The overloaded Foo::operator<<() takes actually two arguments:
The parameter int given as right-hand side
The implicit this from left-hand side.
To allow chaining of this operator, it should return a reference to the left-hand-side (i.e. *this) to become usable at left-hand-side itself.
Sample code:
#include <iostream>
struct Foo {
Foo& operator<<(int a)
{
std::cout << ' ' << a;
return *this;
}
};
int main()
{
Foo foo;
foo << 1 << 2 << 3;
}
Output:
1 2 3
Live demo on coliru
Chaining is enabled by returning a reference to the instance so you can call another method:
class Foo{
private:
std::vector<int> a;
public:
Foo(){}
Foo& operator<< (int a) {
arr.push_back(a);
return *this;
}
};
Now you can call f << 100 << 200 << 42;.
Note that I replaced the array with a std::vector to make Foo less broken (unless you have a descrutor that you did not show it was leaking memory, you could fix that, but then still copying would cause problems, in short you need to respect the rule of 3/5 when you own a resource, using a std::vector makes things much simpler).
PS: Same works for other methods. You simply call another method on the returned reference to this. Note that operators are just methods (with some syntactic sugar) and to see that you can write as well f.operator<<(100).operator<<(200).operator<<(42);.
Return a reference to *this. It's unrelated but you should use a vector to avoid memory leaks. Try to avoid raw new
class Foo{
private:
std::vector<int> a;
public:
Foo &operator<< (int a) {
arr.push_back(a);
return *this;
}
};

Using std::vector, boost::variant, and types with reference fields together

I have the following two classes:
struct A {
A() : state(0) { }
A(int state_arg)
: state{ state_arg } { }
int state;
};
struct B {
B(int state_arg, const int& ref)
: state{ state_arg }, ref{ ref } { }
int state;
const int& ref;
};
I pretend the field ref in the second one to be a reference to an integer in another location, maybe (but not necessary) the field state of some instance of type B.
Now I want to performs some operations over those types, Indeed, I use the boost::variant library.
using my_type = boost::variant<A, B>;
Now when I work with variables of my_type all works as expected. For example:
int main() {
my_type a(A(45));
my_type b(B(45, boost::get<A>(a).state));
A& at = boost::get<A>(a);
B& bt = boost::get<B>(b);
if (at.state == bt.ref) {
std::cout << "AS EXPECTED" << std::endl;
}
// that prints "AS EXPECTED"
}
But when I work with a std::vector of my_type the things go wrong !
int main() {
std::vector<my_type> vec;
vec.push_back(A(45));
vec.push_back(B(45, boost::get<A>(vec[0]).state));
A& at = boost::get<A>(vec[0]);
B& bt = boost::get<B>(vec[1]);
if (at.state == bt.ref) {
std::cout << "SHOULD I EXPECTED THIS ?" << std::endl;
}
// the code doesn't print
}
Now, I want to know what is going on here, i.e
What is occurring that in the code above that the if condition evaluation gives false ?
And is possible, I would like to receive some advice in how to accomplish this tasks.
Thanks in advance.
Problem is that when you add second element to the vector, it reallocates more memory and moves first object to the new location and you have dangled reference. Simple solution would be to reserve enough memory in std::vector in advance to prevent reallocation or use another container that does not move objects. But your original solution has a design flaw - it relies on the fact that object it has reference to should outlive it. But your logic cannot guarantee that so it leads to the issue you see in the std::vector. Same issue could be in the first example if object b would outlive object a somehow. Better solution would be to use smart pointers and let objects of type B hold a shared or weak pointer to object of type A, depends on ownership you want to have. This way you will have shared pointers in std::vector and memory reallocation would not affect you:
struct A {
A() : state(0) { }
A(int state_arg)
: state{ state_arg } { }
int state;
};
typedef std::shared_ptr<A> APtr;
struct B {
B(int state_arg, const APtr& ptr)
: state{ state_arg }, aptr{ ptr } { }
int state;
APtr aptr;
int ref() const { return aptr->state; }
}
typedef std::shared_ptr<B> BPtr;
using my_type = boost::variant<APtr, BPtr>;

C++ assignment on type cast

I stumbled upon something similar today, and subsequently tried a few things out and noticed that the following seems to be legal in G++:
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) { val_ = val; return *this; }
int get() { return val_; }
};
struct B : public A {
A getA() { return (((A)*this) = 20); } // legal?
};
int main() {
A a = 10;
B b;
A c = b.getA();
}
So B::getB returns a type A, after it as assigned the value 20 to itself (via the overloaded A::operator=).
After a few tests, it seems that it returns the correct value (c.get would return 20 as one may expect).
So I'm wondering, is this undefined behavior? If this is the case, what exactly makes it so? If not, what would be the advantages of such code?
After careful examination, with the help of #Kerrek SB and #Aaron McDaid, the following:
return (((A)*this) = 20);
...is like shorthand (yet obscure) syntax for:
A a(*this);
return a.operator=(20);
...or even better:
return A(*this) = 20;
...and is therefore defined behavior.
There are a number of quite separate things going on here. The code is valid, however you have made an incorrect assumption in your question. You said
"B::getA returns [...] , after it as assigned the value 20 to itself"
(my emphasis) This is not correct. getA does not modify the object. To verify this, you can simply place const in the method signature. I'll then fully explain.
A getA() const {
cout << this << " in getA() now" << endl;
return (((A)*this) = 20);
}
So what is going on here? Looking at my sample code (I've copied my transcript to the end of this answer):
A a = 10;
This declares an A with the constructor. Pretty straightfoward. This next line:
B b; b.val_ = 15;
B doesn't have any constructors, so I have to write directly to its val_ member (inherited from A).
Before we consider the next line, A c = b.getA();, we must very carefully consider the simpler expression:
b.getA();
This does not modify b, although it might superfically look like it does.
At the end, my sample code prints out the b.val_ and you see that it equals 15 still. It has not changed to 20. c.val_ has changed to 20 of course.
Look inside getA and you see (((A)*this) = 20). Let's break this down:
this // a pointer to the the variable 'b' in main(). It's of type B*
*this // a reference to 'b'. Of type B&
(A)*this // this copies into a new object of type A.
It's worth pausing here. If this was (A&)*this, or even *((A*)this), then it would be a simpler line. But it's (A)*this and therefore this creates a new object of type A and copies the relevant slice from b into it.
(Extra: You might ask how it can copy the slice in. We have a B& reference and we wish to create a new A. By default, the compiler creates a copy constructor A :: A (const A&). The compiler can use this because a reference B& can be naturally cast to a const A&.)
In particular this != &((A)*this). This might be a surprise to you. (Extra: On the other hand this == &((A&)*this) usually (depending on whether there are virtual methods))
Now that we have this new object, we can look at
((A)*this) = 20
This puts the number into this new value. This statement does not affect this->val_.
It would be an error to change getA such that it returned A&. First off, the return value of operator= is const A&, and therefore you can't return it as a A&. But even if you had const A& as the return type, this would be a reference to a temporary local variable created inside getA. It is undefined to return such things.
Finally, we can see that c will take this copy that is returned by value from getA
A c = b.getA();
That is why the current code, where getA returns the copy by value, is safe and well-defined.
== The full program ==
#include <iostream>
using namespace std;
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) {
cout << this << " in operator= now" << endl; // prove the operator= happens on a different object (the copy)
val_ = val;
return *this;
}
int get() { return val_; }
};
struct B : public A {
A getA() const {
cout << this << " in getA() now" << endl; // the address of b
return (((A)*this) = 20);
// The preceding line does four things:
// 1. Take the current object, *this
// 2. Copy a slice of it into a new temporary object of type A
// 3. Assign 20 to this temporary copy
// 4. Return this by value
} // legal? Yes
};
int main() {
A a = 10;
B b; b.val_ = 15;
A c = b.getA();
cout << b.get() << endl; // expect 15
cout << c.get() << endl; // expect 20
B* b2 = &b;
A a2 = *b2;
cout << b2->get() << endl; // expect 15
cout << a2.get() << endl; // expect 15
}

Why aren't these shared_ptrs pointing to the same container?

I have a class Model:
class Model
{
...
boost::shared_ptr<Deck> _deck;
boost::shared_ptr<CardStack> _stack[22];
};
Deck inherits from CardStack.
I tried to make _stack[0] point to the same thing that _deck points to by going:
{
_deck = boost::shared_ptr<Deck>(new Deck());
_stack[0] = _deck;
}
It seems that the assignment to _deck of _stack[0] results in a copy of _deck being made. (I know this because modifications to _stack[0] do not result in modifications to _deck.) How can I get them to point to the same thing?
Ok - no copy constructor is being called. I have verified this by implementing it and seeing if it gets called - it doesn't.
However - I have a function that operates on CardStack objects:
void TransferSingleCard(CardStack & src, CardStack & dst, Face f)
{
if( !src._cards.empty() )
{
src._cards.back().SetFace(f);
dst.PushCard(src._cards.back());
src._cards.pop_back();
}
}
Now - when I call:
{
TransferSingleCard(*_stack[DECK], _someotherplace, FACEDOWN);
std::cout << *_stack[DECK];
std::cout << *_deck;
}
I get this output (where std::cout on a CardStack will print out the size of that stack):
Num(103) TOP
Num(104) TOP
... so I've concluded (incorrectly?) that _stack[DECK] points to something different.
The Deck
class Deck : public CardStack
{
public:
Deck(int numsuits=2, StackIndex index = NO_SUCH_STACK );
Deck::Deck( const Deck & d);
int DealsLeft() const;
void RecalcDealsLeft();
private:
int _dealsleft;
};
Not clear what you are asking about - consider this code:
#include <iostream>
#include "boost/shared_ptr.hpp"
using namespace std;
struct A {
virtual ~A() {
cout << "destroyed" << endl;
}
};
struct B : public A {
};
int main() {
boost::shared_ptr<B> b( new B );
boost::shared_ptr<A> a;
a = b;
}
Only one "destroy" message appears, indicating that no copy has been made.
This example - derives from #Neil's answer, tries to emulate what you say is happening. Could you check that it works as expected (A and B have the same count) on your system.
Then we could try and modify this code or your code until they match.
#include <boost/shared_ptr.hpp>
#include <iostream>
class A {
public:
virtual ~A()
{
std::cerr << "Delete A" << std::endl;
}
int _count;
void decrement()
{
_count --;
}
};
class B : public A {
public:
virtual ~B()
{
std::cerr << "Delete B" << std::endl;
}
};
int main()
{
boost::shared_ptr<B> b(new B);
b->_count = 104;
boost::shared_ptr<A> a;
a = b;
a->decrement();
std::cerr << "A:" << a->_count << std::endl;
std::cerr << "B:" << b->_count << std::endl;
return 0;
}
EDIT:
So from the comment, we know the original pointers are correct, so now we need to trace.
Either:
log pointers to see when they change.
Use watchpoints in a debugger to see when the pointer changes.
Use a third shared pointer to see which pointer is changed.
Introduce a function that changes both pointers at the same time.
I think the problem is that you're assigning between different types here. boost::shared_ptr is a template and templates are not polymorphic even if the type in them is. So what's happening is that your compiler sees the assignment from boost::shared_ptr<Deck> to boost::shared_ptr<CardStack> and notices that it can make the assignment by calling the copy constructor for CardStack to duplicate the Deck object.
I think what you want the assignment to look like is something like this:
_stack[0] = boost::static_pointer_cast<CardStack>(_deck);
Which will do the conversion the way you expect it to.
I think you may want shared_array for _stack . . . Take a look at the documentation on shared_ptr;from boost.org, specifically:
http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm
"Normally, a shared_ptr cannot
correctly hold a pointer to a
dynamically allocated array. See
shared_array for that usage."
Also, be aware of the T* get() function (not to be used without good reason) which returns the raw pointer being held by the managed pointer (shared_ptr in this case).