How to forbid object copying in swift3? - swift3

I want to be sure that every instance of the object is used by reference. Instantiated it could be several times but should not be copied.
F.e. in c++ it is easy to do:
class A {
public:
A(const A&) = delete;
A& operator = (const A&) = delete;
};
That is. Of course smbd could try to make some hack in memory - but it is not useful and not so easy. You should know exactly the memory layout of your object and all fields it encapsulates. I do not want smth special - just equivalent of the code above in swift 3.

In Swift, classes are reference types. So they already do what you want: they can be held by reference only. They'll always be on the heap, and assignments will act to assign references, not class contents. So just make sure you declare your object as a class rather than a struct — unlike C++ the primary difference between the two in Swift is reference type versus value type.

Related

Can I use the = operator to assign one object's values to another object, without overloading the operator?

this was a recent T/F question that came up in my cs course that I found a bit confusing.
The textbook states:
The = operator may be used to assign one object's data to another object, or to initialize one object with another object's data. By default, each member of one object is copied to its counterpart in the other object.
The question verbatim was:
You cannot use the = operator to assign one object's values to another object, unless you overload the operator. T/F?
Judging from that particular paragraph of the textbook, I answered false. However, it turns out the quiz answer was actually true.
When I looked up the question online, I saw other sources listing the answer as "false" as well. Granted, these were just generic flashcard / quiz websites, so I don't put much stock in them.
Basically, I'm just curious what the real answer is for future studying purposes.
P.S.: The textbook later goes on to state: "In order to change the way the assignment operator works, it must be overloaded. Operator overloading permits you to redefine an existing operator’s behavior when used with a class
object."
I feel like this is related and supports the "true" answer, but I'm not really sure.
The statement
” You cannot use the = operator to assign one object's values to another object, unless you overload the operator.
… is trivially false, because you can assign to e.g. an int variable. Which is an object. In C++.
Possibly they intended to write “class-type object”, but even so it's false. E.g. any POD (Plain Old Data) class type object is assignable and lacks an overloaded assignment operator.
However, there are cases where you want or need to prohibit or take charge of assignment.
If you don't implement the assignment operator yourself, the compiler will generate one for you, which will copy the data from the source to the destination, invoking assignment operators of the members of your class where possible/necessary.
This does not work if your class e.g. features const members, and it does not yield the desired result if your class contains pointers to dynamically allocated objects.
So, I would also say that the statement is false.
That's a trick question. The syntactic answer is "false" but the semantic answer is "maybe".
struct Foo
{
int a;
double b;
};
Foo foo1;
Foo foo2;
foo2 = foo1; // Ok in both senses.
struct Bar
{
Bar() : arr(new int[20]) {}
~Bar() { delete [] arr; }
int* arr;
};
Bar bar1;
Bar bar2;
bar2 = bar1; // Ok in syntax not in semantics
// This will lead to UB
In C++, when User-Defined Types such as class and struct are involved then its better to overload operator= for the Type. Using default assignment operator with object of class or struct will involve Shallow Copy. Shallow Copy sometimes lead to undefined behavior when the class or struct objects have dynamically allocated memory inside them.
Appropriately overloading operator= for class and struct types will lead to Deep Copy which is the correct method of assigning an object ObjA to object ObjB (ObjB = ObjA) when ObjA and ObjB are objects of some class or struct and contain dynamically allocated memory inside them.
The = operator may be used to assign one object's data to another object, or to initialize one object with another object's data. By default, each member of one object is copied to its counterpart in the other object. This is true when object of class/struct has only static fundamental type of data inside it. Here,
by static it means that all the memory requirement of object is fixed at compile time only.
You cannot use the default = operator to assign one object's values to another object, unless you overload the operator. This is true when object of class/struct has some dynamically allocated memory inside it, possibly by using pointers.
For more reference see:
What is the difference between a deep copy and a shallow copy?
You cannot use the = operator to assign one object's values to another object, unless you overload the operator. T/F?
Ans: F
You can assign one object's values to another object without overloading = operator, as compiler by default defines assignment operator for the class in all case except for below
you have explicitly declared a copy-assignment operator (for class X an operator = taking X, X& or const X&) )
there is a member in your class that is not assignable (such as a reference, a const object or a class with no or inaccessible assignment operator)
But you need to understand why it becomes mandatory to overload the assignment operator in case you are having user defined members or having dynamic memory allocation,for this read concept of shallow and deep copy

How to have const members in stl container values in C++?

I like to make my C++ member variables const if they should not be changed once the object is constructed, however, sometimes they need to be modified by STL. For example, if I have a vector of my class with const members and I try to swap two elements in the vector, STL tries to use the default generated operator=() and fails because of the const member variables.
I feel like the operator=() is like a constructor in that the whole object is being created and thus would like some way to allow operator=() while still having my const member variables.
Is there anyway to do this in C++03? If not, what about in C++11, perhaps in-place construction is for this?
class Foo {
const int _id;
static int _generate_unique_id();
public:
Foo()
: _id(_generate_unique_id()) {
}
};
vector<Foo> foo_vector;
// Fill foo_vector with several entries:
// [...]
// Try to swap the first and second elements of the vector:
swap(*foo_vector.begin(), *(foo_vector.begin() + 1));
// The above fails to compile due to const member variable _id
// prohibits us from using the default assignment operator.
A solution for storing not assignable objects in standard library containers is storing (smart) pointers to the objects. Not always ideal, but workable.
For example, if I have a vector of my class with const members and I try to swap two elements in the vector, STL tries to use the default generated operator=() and fails because of the const member variables.
Implement the "big three and a half" (default and copy constructor, assignment operator and swap), with the assignment operator explicitly skipping the reassignment if _id.
What you want is a thing like the Java immutable idiom.
This is awesome with pointers (and thus, garbage collected languages) and less awesome with value-semantic languages like C++.
You have two solutions:
1 - Make your object immutable in the interface
The member is private (or it should be), so no one but the class itself (and its friends) can modify it. So all you need is to make sure no one does inside the class (which you control) and offer no way in the protected/public interface to leave others the power to do so.
TL;DR: Make your object non const. Don't modify it inside the class. Add a const getter. Remove the setter (if any).
2 - Use a std::unique_ptr<const Data>
Now we follow the Java idiom. The object is const, but the pointer can be reattributed, which is exactly what you want.
This is actually better than the const Data * member alternative because of its exception safety.
Bonus: Don't manually call the destructor to reconstruct again the object
There's an answer proposing that.
As mentionned first by sehe, don't do that.
Your point is to increase the quality of your code, which means your code will need to be exception safe, at one point or the other. And manually playing with your object lifetime will make it unusable in quality code.
Read Herb Sutter's article on the subject: http://www.gotw.ca/gotw/023.htm
const on members doesn't just prevent the programmer from modifying the value of the member during its lifetime; it also enables compiler optimisations by specifying that attempts to modify it are undefined behaviour (see const member and assignment operator. How to avoid the undefined behavior?).
One way to do what you want is to write a nonmodifiable container that gives semantic const while leaving you as the programmer the possibility of modifying the contained value:
template<typename T> class nonmodifiable {
T t;
public:
nonmodifiable(T t): t{std::move(t)} {}
operator const T &() const { return t; }
nonmodifiable &operator=(const nonmodifiable &) = delete;
};
You can now write:
class Foo {
nonmodifiable<int> _id;
// etc.
};
and because neither _id nor its contained value are const, use the destruct-placement new dance to reassign its value:
Foo &operator=(const Foo &foo) {
if (this != &foo) {
_id.~nonmodifiable<int>();
new (&_id) nonmodifiable<int>(foo._id);
}
return this;
}

Enforce Memory alignment in C++

I want to design an API, which internally uses EIGEN.
Based on http://eigen.tuxfamily.org/dox/TopicPassingByValue.html, if a class have a Eigen object as member, it can not be passed by value.
Is there any straight forward way to tell compiler (e.g. g++) the my object can not be passed by value?
You can simply make the copy constructor unavailable. You can achieve this by using Boost and inheriting from boost::noncopyable, or by making the copy constructor private:
struct Foo
{
private:
Foo(Foo const &) { }
};
Or in the new C++ by explicitly deleting it:
struct Foo
{
Foo(Foo const &) = delete;
Foo(Foo &&) = delete;
};
You should probably also make your class unassignable by doing the same to the assignment operator (and boost::noncopyable takes care of this for you).
To prevent a C++ object from being copied, declare a copy constructor and assignment operator, but make those functions private. (Since they are not called by anything, you don't have to bother implementing them.)
The documentation you cited looks bogus. How is it that this Eigen::Vector2d object is able to achieve its proper alignment in the original object, and why wouldn't the copy object have the same alignment?
The extraordinary piece of information required for that to make sense is not given.
Just make a copy constructor/copy operator private.

is it possible to restrict class instances to be used only as temporaries?

is it possible to restrict class instances to be used only as rvalues (e.g. temporaries)?
for example, I have class Wrapper whose constructor takes A const& and saves this reference in its member. It's a dangerous because lifetime of Wrapper instance cannot be longer than lifetime of A instance, but it's fine if Wrapper is temporary.
I think that even wanting to do this is a sign of a really bad design.
However, you could make all constructors private and make a friend function that returns an rvalue. That should do the trick.
I don't think it would be safe:
const A &a = YourClass( tmp );
YourClass in this case is the class you're looking for which only allow temporary instances, tmp is the temporary value you pass to the constructor.
It's possible (ie: safe, defined behavior) to have a constant reference to a temporary (ie: a), but the temporary itself (such instance of YourClass) has got a reference to tmp which is no longer valid after that expression is evaluated.
Not exactly the answer you are looking for, but have you thought about weak pointers? (for example, boost::weak_ptr). In this case, the original A would be held in a shared_ptr and the Wrapper constructor accepts a weak_ptr. The neat thing with this approach is that, before each usage of the weak_ptr, you can attempt to lock() which will give you a shared_ptr - if that fails, you know that A is gone and Wrapper cannot function... But it's handled cleanly...
This might do the job unless your class has public data members.
Basically, the idea is not to restrict the construction of the wrapper but to make sure that instances can be used (just like you said) only as long as they are temporary values. One can achieve this by overloading all methods and deleting (or making them private) those that refer to const&.
Here's a simple example:
class Wrapper
{
public:
Wrapper() = default;
Wrapper(const std::string& name) : name(name) {}
void process() && { std::cout << "Greetings from " << name << std::endl; }
// Only temporary instances of this class are allowed!
void process() const & = delete;
private:
std::string name;
};
And some use cases:
Wrapper("John").process(); // intended use case
Wrapper j; // create whatever you want
j.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
std::move(j).process(); // this is still possible
const Wrapper& t = Wrapper(); // bind the temporary to a const reference - not a problem because ...
t.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
The obvious disadvantages are:
You have to overload every public member function.
The error message is delayed and not very informative.
A similar thing has been done in the standard. The make routines for std::reference_wrapper do not accept temporaries.
Note that they considered another subtlety: the overload uses const T&& instead of T&&. This can be important in our case as well. For example, if your wrapper is deliberately designed to be noncopyable and you use make routines such as
const Wrapper make_wrapper();
instead of
Wrapper make_wrapper();
In this case, you might want to replace
void process() &&;
by
void process() const &&;
I'd not bother enforcing this at compile time, as there are always going to be corner cases where this would be overly restrictive, limiting the usefulness of the class, but rather wrap tools like valgrind or Purify so I can spot places where invalidated references are used.
I believe in C++17 and later you can get approximately what you want by doing the following:
Delete the move constructor for your type (and don't define a copy constructor).
Always accept your type by value in APIs.
So, for example:
#include <type_traits>
#include <utility>
// A non-moveable, non-copyable type.
struct CantMove {
CantMove(CantMove&&) = delete;
CantMove(int) {} // Some other constructor
};
static_assert(!std::is_move_constructible_v<CantMove>);
static_assert(!std::is_copy_constructible_v<CantMove>);
// A function that accepts it by value.
bool AcceptByValue(CantMove input) { return true; }
// It's possible to call the value-accepting API when the input is a prvalue
// (which in previous versions of C++ would have been a temporary).
bool unused = AcceptByValue(CantMove(0));
// But it's not possible to call with a named value, even when casted to an
// rvalue reference. This doesn't compile.
CantMove cant_move(0);
bool unused_2 = AcceptByValue(std::move(cant_move));
It's possible to provide the value-accepting function with what we previously called a temporary because guaranteed copy elision says that there isn't even a temporary involved anymore—the only CantMove object created is the function parameter itself, so there is no move- or copy-construction involved. In contrast it's not possible to call with std::move(cant_move) because that would involve move-constructing the function parameter, and the type is not move-constructible.
Of course it's still possible to initialize a CantMove directly:
CantMove foo{0};
But if you own all of the APIs that accept a CantMove and make them all accept by value, then you can't actually do anything with foo afterward. This means it would be hard for a user to do this by mistake and not realize the problem.
Yes, you could.
You would make the constructor and regular copy-constructor/assign private but make the r-value move semantics (C++0x) public.
You would have a static or friend constructor to create the temporary.
In 2003 C++ you would also be able to use this to bind to a const reference.
Of course you'd have the issue that your const reference would probably become invalidated after the statement.

How do use a std::auto_ptr in a class you have to copy construct?

I have class foo that contains a std::auto_ptr member that I would like to copy construct but this does not appear to be allowed. There's a similar thing for the assignment. See the following example:
struct foo
{
private:
int _a;
std::string _b;
std::auto_ptr< bar > _c;
public:
foo(const foo& rhs)
: _a(rhs._a)
, _b(rhs._b)
, _c(rhs._c)
// error: Cannot mutate rhs._c to give up ownership - D'Oh!
{
}
foo& operator=(const foo& rhs)
{
_a = rhs._a;
_b = rhs._b;
_c = rhs._c;
// error: Same problem again.
}
};
I could just declare _c as mutable but I'm not sure this is correct. Does anyone have a better solution?
EDIT
OK, I'm not getting the kind of answer that I was expecting so I'll be a little more specific about the problem.
An object of type foo is created on the stack and passed by value into a container class (not stl) and then goes out of scope. I don't have any control over the container code. (It's actually an active queue implementation, with bugs.)
The bar class is a fairly heavyweight parser. It has very poor performance on new and delete so even if it was copy constructable, it would be way too expensive.
We can guarantee that when a bar object is created, it will only ever need to be owned in 1 place at a time. In this case it is being passed between threads and deleted when the transaction is completed. This is why I was hoping to use a std::autp_ptr.
I am very willing to consider boost smart pointers but I was hoping to guarantee this uniqueness if there is an alternative.
You might want to try following code:
foo(const foo& rhs)
: _a(rhs._a)
, _b(rhs._b)
, _c(_rhs._c.get() ? new bar(*_rhs._c.get()) : 0)
{
}
(Assignment operator is similar.)
However this will only work if bar is CopyConstructible and if this indeed does what you want. The thing is that both foo objects (_rhs and constructed one) will have different pointers in _c.
If you want them to share the pointer then you must not use auto_ptr as it does not support shared ownership. Consider in such case use of shared_ptr from Boost.SmartPtr for example (which will be included in new C++ standard). Or any other shared pointer implementation as this is such a common concept that lots of implementations are available.
As you have discovered you can't copy a std::auto_ptr like that. After the copy who owns the object pointed to? Instead you should use a reference counted smart pointer. The Boost library has a shared_ptr you could use.
First, I'd avoid auto_ptr
Transfer of ownership is good in some scenarios, but I find they are rare, and "full fledged" smart pointer libraries are now available easily. (IIRC auto_ptr was a compromise to include at least one example in the standard library, without the delays that a good implementation would have required).
See, for example here
or here
Decide on semantics
Should the copy of foo hold a reference to the same instance of bar? In that case, use boost::shared_ptr or (boost::intrusive_ptr), or a similar library.
Or should a deep copy be created?
(That may sometimes be required, e.g. when having delay-created state). I don't know any standard implementation of that concept, but it's not to complex to build that similar to existing smart pointers.
// roughly, incomplete, probably broken:
template <typename T>
class deep_copy_ptr
{
T * p;
public:
deep_copy_ptr() : p(0) {}
deep_copy_ptr(T * p_) : p(p_) {}
deep_copy_ptr(deep_copy_ptr<T> const & rhs)
{
p = rhs.p ? new T(*rhs.p) : 0;
}
deep_copy_ptr<T> & operator=(deep_copy_ptr<T> const & rhs)
{
if (p != rhs.p)
{
deep_copy_ptr<T> copy(rhs);
swap(copy);
}
}
// ...
}
The std::auto_ptr is a good tool for managing dynamic object in C++ but in order to use it effectivelly it's important to unserstand how auto_ptr works. This article explains why, when and where this smart pointer should be used.
In your case, first of all your should decide what you want to do with the object inside your auto_ptr. Should it be cloned or shared?
If it should be cloned, make sure it has a copy constructor and then your create a new auto_ptr which contains a copy of your the object see Adam Badura's answer.
If it should shared, you should use boost::shared_ptr as Martin Liversage suggested.
If I have class containing an auto_ptr, and want deep-copy semantics, I generatally only do this for classes that have a virtual copy operator, i.e. clone().
Then, within the copy constructor, I initialize the auto_ptr to a clone() of the other; e.g.
class Foo
{
public:
Foo(const Foo& rhs) : m_ptr(rhs.m_ptr->clone());
private:
std::auto_ptr<T> m_ptr;
};
clone() is typically implemented as follows:
class T
{
std::auto_ptr<T> clone() const
{
return std::auto_ptr<T>(new T(*this));
}
};
We are imposing the condition that T is clonable, but this condition is essentially imposed by having a copiable class with an auto_ptr member.
The whole idea of the auto_ptr is that there's only one owner of the referred to object. This implies you cannot copy the pointer without removing the original ownership.
Since you cannot copy it, you also can't copy an object containing an auto_ptr.
You might try to use move-semantics by e.g. using std::swap instead of copy.
My first choice would be to avoid auto_ptr in this situation altogether. But if I were backed against a wall, I might try to use the keyword mutable in the declaration of _c - this will allow it to be modified even from a const reference.
Given the edit, then it appears you want tranfer of ownership semantics.
In that case, then you'll want to have your copy constructor and assignment operator accept non-const references to their arguments, and perform the initialization/assignment there.
You can't use const references in a copy constructor or assignment operator that involves an auto_ptr<>. Remove the const. In other words, use declarations like
foo(foo & rhs);
foo & operator=(foo & rhs);
These forms are explicitly mentioned in the Standard, primarily in section 12.8. They should be usable in any standard-conforming implementation. In fact, paragraphs 5 and 10 of 12.8 says that the implicitly defined copy constructor and assignment operator (respectively) will take a non-const reference if any of the members require it.