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.
Related
I often find myself using unique pointers in C++ when I want polymorphic behaviour. I typically implement pure abstract classes something like the below:
class A {
public:
virtual A* clone() const = 0; // returns a pointer to a deep copy of A
// other methods go here
};
The clone method comes in handy when I want to embellish another class with its own instance of A, for example:
#include <memory>
class B {
private:
std::unique_ptr<A> a_ptr;
public:
// ctor
B(const A& a) {
a_ptr = std::unique_ptr<A>(a.clone());
//...
}
// copy ctor
B(const B& other) : B(*other.a_ptr) {}
};
I invariably end up implementing the copy constructor in B to avoid a compiler error (MSVC gives a vague message about attempting to reference a deleted function), which makes complete sense because of the unique pointer. My questions can be summarised as follows:
Do I actually need the copy constructor in B? Perhaps there's a better pattern that would allow me to avoid it altogether.
If yes to 1, can I stop there? Will I ever need to implement the other default functions? I.e. is there any scenario where I need a default constructor and destructor also?
In practice, whenever I feel I need to implement the default functions, I typically implement a move-constructor alongside the other three; I usually use the copy-and-swap-idiom (as per GManNickG's answer in this thread). I assume this wouldn't change anything, but maybe I am wrong!
Thanks a lot!
First, I think the signature of your clone function could be
virtual std::unique_ptr<A> clone() = 0;
as you want deep copies of A instances and exclusive ownership within B. Second, you indeed have to define a copy constructor for your class when you want it to be copyable. Same for an assignment operator. This is due to the fact that std::unique_ptr is a move-only type, which hinders the compiler to generate default implementations.
Other special member functions are not needed, though they might make sense. The compiler won't generate move constructor and move assignment operator for you (as you ship your own copy/assignment functions), though in your case, you can = default; them easily. The destructor can equally well be defined with = default;, which would be in line with the core guidelines.
Note that defining the destructor via = default should be done in a translation unit, as std::unique_ptr requires the full type do be known upon freeing its resource.
Whether you need a default constructor totally depends on how yo want to use the class B.
As #lubgr mentioned in his answer, You should return unique_ptr not a raw one from the clone function. Anyway, going to Your questions:
Do You need a copy constructor in B? Well it depends on Your use cases, but if You copy objects of class B You may need one. But as You said, You do it quite often, so it would be wise to consider more generic approach. One of these would be creating a wrapper for unique_ptr which would have copy constructor and which would make a deep copy of this pointer in this copy constructor.
Consider following example:
template<class T>
class unique_ptr_wrap {
public:
unique_ptr_wrap(std::unique_ptr< T > _ptr) : m_ptr(std::move(_ptr)){}
unique_ptr_wrap(const unique_ptr_wrap &_wrap){
m_ptr = _wrap->clone();
}
unique_ptr_wrap(unique_ptr_wrap &&_wrap){
m_ptr = std::move(_wrap.m_ptr);
}
T *operator->() const {
return m_ptr.get();
}
T &operator*() const {
return *m_ptr;
}
private:
std::unique_ptr< T > m_ptr;
};
This again depends on Your needs. I personally would recommend overloading move constructor as well, to make it use less dynamic allocations (but this may be premateure optimization which is root of all evil).
I am new to object oriented programming, and this may be a silly question, but I don't understand why is using class A code better to use than class B if you want to create copy of one object.
class A {
int num;
public:
A(const A &ref) : num(ref.num) {};
};
class B {
int num;
public:
B(B *ptToClass) : num(ptToClass->num) {};
};
If I got this right, copy constructor is used in class A.
If you don't declare a copy constructor for your class, the compiler will declare one for you anyway. Classes have to have copy constructors. They're baked into the language and have special status. The language doesn't work without them.
Possibly the best example is that copy constructors are needed when passing by value. The compiler is going to implicitly call the copy constructor when you pass by value. It's not going to call the constructor B::B(B*).
So if you want your class to be copyable, you should define the copying logic in the copy constructor. It's just easier.
Class A is flexible and safe: you create a copy from any A object you have, even if it's a temporary one.
Class B is less safe as you could invoke the constructor with a nullptr. It's less flexible because you can only use ypur constructor to copy an object from which you can get the address and which is not const.
B b1(...);
const B b2(...);
B fb(); // function returning a B
B b3(&b1);
B b4(&b2); // error b2 is const
B b5(&fb()); // error you can't take adress of a temporary
The thing is that if a constructor is considered to be a copy constructor by the compiler, it is used in special ways. For instance, if you have a function that takes a parameter of your type A by copy, like this:
void function(A obj) {
// Do something with A
// ...
}
And then you call that function:
int main() {
A a_obj;
function(a_obj);
}
the object obj received by function will be created by the copy constructor you provided. So, it is a nice thing to provide copy constructor for your classes that are meant to be copied, so that them fits more nicely with the languages features and libraries.
There is no problem in creating a constructor of the kind in your class B, if that fit your needs in your application, but that will not be understood by the compiler as a copy constructor, and won't be used when the compiler or libraries needs to copy your objects.
It is forbidden by standard to use pointers in copy constructors:
C++ draft standard n3376 - section 12.8.2:
A non-template constructor for class X is a copy constructor if its
first parameter is of type X&, const X&, volatile X& or const volatile
X&, and either there are no other parameters or else all other
parameters have default arguments
Why is the argument of the copy constructor a reference rather than a pointer?
I think a more appropriate question to ask is: when to provide a user-defined copy constructor over the default one provided by the compiler?
As we know, the compiler provides a copy constructor (the default one) which does a memberwise copy.
This memberwise copy is not bad as long as the class is a simple concrete type (that behaves for the most part like a built-in type). But for complex concrete types or classes with hierarchies, memberwise copy is not a good idea, and the programmer is highly advised to provide his own implementation of the copy constructor (that is, provide user-defined copy constructor).
As a thumb rule, it is a good idea to provide user-defined copy constructor in the class.
Is the following assignment valid?
class A {
int a;
public:
A(int k): a(k){}
}
void main() {
A first (5);
A second;
second = first;
}
If it is valid, what happens for second? Does C++ makes a deep copy? Or a shallow copy?
Perhaps you are new to C++, perhaps a student?
You are lucky, since the data member for your A class is an integer. Which is a plain old data type. Called POD for short. BTW: You tagged your question with copy-constructor, but demonstrated in your example an assignment operator.
They are two different things.
A copy constructor makes a new instance based off of another instance. Like this:
class A
{
public:
A(A& other) { ... }
};
An assignment operator looks like this:
class A
{
public:
const A& operator=(const A& other) { ... }
};
Since you did not provide your own assignment operator, the compiler made one for you. In fact the compiler will also make a destructor for you too. Isn't that nice? Well don't always trust your compiler. If your classes have anything beyond Plain old Data, then please get in the habit of providing your own constructors, destructors, assignment operators. It's a rule I live by. I'd hate to have a bug that takes 2 days to track down to say... a memory leak due to my forgetting to deallocate memory in a destructor.
In your case, the compiler made a shallow copy for you. A compiler will never make a deep copy for you. You have to do that yourself.
Since you wrote one form of constructor, compiler will not provide default constructor so your declaration 'A second;' will not compile. You could possibly do A second(0); and then second = first;
I have a codebase that I'd like to switch from C++03 to C++11.
As I understand, some classes will benefit from the change by having an implicit default move constructor (and the move assignment operator that comes along). While I'm totally ok with that (I even think it is a nice thing) I'm a bit afraid of the effects that such implicit constructors might have on some non-copyable classes I have.
One example I have is a class that wraps an iconv_t handle from libiconv to leverage RAII.
More explicitely, the class is as follow:
class iconv_wrapper
{
public:
iconv_wrapper() : m_iconv(iconv_open()) {}
~iconv_wrapper() { iconv_close(m_iconv); }
private:
// Not implemented: non copyable. Should probably be = delete; in C++11.
iconv_wrapper(const iconv_wrapper&);
iconv_wrapper& operator=(const iconv_wrapper&);
iconv_t m_iconv;
};
My concern is: if an instance of this class happened to be moved, this would result in a double call to iconv_close(). As iconv_t is a "dumb" integral type, I don't expect the default implementation of iconv_wrapper(iconv_wrapper&&) to nullify the m_iconv member of the R-value. Even if it did, the destructor is not implemented to handle this properly.
So my questions are:
Are my concerns legitimate ? Am I right that the default movable constructor/operator= will be incorrect in such a case ?
What changes can I make to port this code nicely to C++11 ? (I was suggested std::unique_ptr but I couldn't make this work nicely, as it expects a pointer, not some opaque type)
It won't be moved. Because you have a user declared copy constructor, copy assignment operator and destructor, the move constructor and move assignment operator will not be generated. Actually, any one of those three declared would suppress automatic generation of the move constructor and move assignment operator.
If you want to make it more C++11 friendly, you could add a move constructor and move assignment operator, as in (warning: never compiled or tested):
class iconv_wrapper
{
public:
iconv_wrapper() : m_iconv(iconv_open()) {}
~iconv_wrapper() { if ((iconv_t)-1 != m_iconv) iconv_close(m_iconv); }
iconv_wrapper(iconv_wrapper&& that) noexcept { std::swap(m_iconv, that.m_iconv); }
iconv_wrapper& operator=(iconv_wrapper&& that) noexcept { std::swap(m_iconv, that.m_iconv); return *this; }
private:
iconv_t m_iconv = (icontv_t)-1;
};
A reason you might want to do this is so you can store these objects (or other types which contain these objects) in a vector.
My current implementation uses lots of copy constructors with this syntax
MyClass::Myclass(Myclass* my_class)
Is it really (functionnaly) different from
MyClass::MyClass(const MyClass& my_class)
and why?
I was adviced that first solution was not a true copy constructor. However, making the change implies quite a lot of refactoring.
Thanks!!!
It's different in the sense that the first isn't a copy constructor, but a conversion constructor. It converts from a MyClass* to a MyClass.
By definition, a copy-constructor has one of the following signatures:
MyClass(MyClass& my_class)
MyClass(const MyClass& my_class)
//....
//combination of cv-qualifiers and other arguments that have default values
12.8. Copying class objects
2) A non-template constructor for class X is a copy constructor if its
first parameter is of type X&, const X&, volatile X& or const volatile
X&, and either there are no other parameters or else all other
parameters have default arguments (8.3.6).113) [ Example: X::X(const
X&) and X::X(X&,int=1) are copy constructors.
EDIT: you seem to be confusing the two.
Say you have:
struct A
{
A();
A(A* other);
A(const A& other);
};
A a; //uses default constructor
A b(a); //uses copy constructor
A c(&a); //uses conversion constructor
They serve different purposes alltogether.
The first version is not a copy constructor. Simple as that. It's just another constructor.
A copy constructor for a class X must have signature (X &, ...) or (X const &, ...) or (X volatile &, ...) or (X const volatile &, ...), where all arguments but the first have default values if they are present (and it must not be a template).
That said, you should think very carefully about why you're violating the Rule of Zero: Most well-designed classes shouldn't have any user-defined copy-constructor, copy-assignment operator or destructor at all, and instead rely on well-designed members. The fact that your current constructor takes a pointer makes me wonder if your code behaves correctly for something like MyClass x = y; — worth checking.
Certain language constructs call for a copy constructor:
passing by value
returning by value
copy-style initialization (although the copy is often elided in that case)
If the language calls for a copy, and you have provided a copy constructor, then it can be used (assuming the cv-qualifications are OK, of course).
Since you have not provided a copy constructor, you will get the compiler-generated copy constructor instead. This works by copying each data member, even if that's not the right thing to do for your class. For example if your not-a-copy-constructor explicitly does any deep copies or allocates resources, then you need to suppress the compiler-generated copy.
If the compiler-generated copy works for your class, then your not-a-copy-constructor is mostly harmless. I don't think it's a particularly good idea, though:
void some_function(const MyClass &foo);
MyClass *ptr = new MyClass();
const MyClass *ptr2 = ptr;
some_function(ptr); // compiles, but copies *ptr and uses the copy
MyClass bar(ptr2); // doesn't compile -- requires pointer-to-non-const
Even assuming that the compiler-generated copy is no good for your class, making the necessary change need not require a lot of refactoring. Suppose that your not-a-constructor doesn't actually modify the object pointed to by its argument, so after fixing the signature you have:
MyClass::MyClass(const MyClass* my_class) {
// maybe treat null pointer specially
// do stuff here
}
You need:
MyClass::MyClass(const MyClass& my_class) {
do_stuff(my_class);
}
MyClass::MyClass(const MyClass* my_class) {
// maybe treat null pointer specially
do_stuff(*my_class);
}
MyClass::do_stuff(const MyClass& my_class) {
// do stuff here
}
You also need to copy any initializer list from the old constructor to the new one, and modify it for the fact that my_class isn't a pointer in the new one.
Removing the old constructor might require a lot of refactoring, since you have to edit any code that uses it. You don't have to remove the old constructor in order to fix any problems with the default copy constructor, though.
The first example is not a copy constructor. This means that when you provide it, the compiler still provides you with a default copy constructor with signature equivalent to
MyClass(const MyClass& my_class);
If you are doing something special with your constructor, and the compiler provided copy constructor does not follow that logic, you should either implement a copy constructor or find a way to disable it.
Why would I want to use a copy constructor instead of a conversion constructor?
It can be problematic if you give MyClass objects to some code that expect your copy-constructor to be valid.
This is the case for STL containers. For instance, if you use a std::vector<MyClass>, you must be aware that vectors are allowed to move elements around for reallocation using their copy constructors.
The default constructor provided by the compiler will perform a shallow copy, calling copy constructors of every attributes, making simple copies for base type like pointers. If you want some form of deep copy you will have to properly rewrite the copy constructor of MyClass