In C++0x, is it legal / expected that some classes can be copied but not moved? I'm looking at implementing a heterogenous class that resizes, and I'm not sure I could handle it if some classes needed copying and some needed moving.
Yes, it's legal for a class to be copyable but not movable:
class MyClass {
public:
/* Copyable... */
MyClass(const MyClass&);
MyClass& operator= (const MyClass&);
/* ... but not movable. */
MyClass(MyClass&&) = delete;
MyClass& operator= (MyClass&&) = delete;
};
However, I can't think of a good reason as to why anyone would want to do this. Knowing C++ coders (like me!) though, I think that you should anticipate that this might come up.
Out of curiosity, what code are you relying on that would break if a class was copyable but not movable?
I'm quite sure that making the move constructor protected/private is a way of limiting the ability to move objects of that class. If you can expect that in a template? I don't think so. You'd need std::enable_if for that kind of check.
Related
I'm just wondering if move semantics are restricted to syntax style B.
More specifically, with style B the object is created on the stack and moved. With style A, the object is created on the heap, but it seems can't be moved.
The question very specifically is, can you use move semantics such that the temp is created with NEW? If so, how?
//move c'tor
A(A&& other) : num(other.num), s(other.s){
other.num = 0;
other.s = nullptr; //dyn alloc obj
}
If you do this, it doesn't work (syntax style A).
A a2(new A("blah")); //error
A a2(move(new A("blah"))); //error
This is ok (syntax style B)
A a2(A("blah")); //uses c'tor once
A a2(move(A("blah"))) //uses c'tor followed by move c'tor
You seem to be confused about a number of things, so I'll try to shed some light. You probably know most of this already.
Move semantics were designed to allow objects to transfer ownership of their data to another object. This was motivated largely to avoid copying from temporary objects that didn't need it.
The move constructor is much like the copy constructor, A(const A&), but only accepts a non-const xvalue of the same type, A(A&&) (think of it as an expiring value). Therefore, this constructor can be invoked when given something like a return value from a function or a variable moved via std::move.
Now, the function std::move in itself is a bit of a misnomer, it doesn't actually do anything. All it does it cast a T or T& into a T&&.
To address your question directly, nothing I've mentioned is specific to where the moving object is located, but it is specific about the types. A("blah") calls the constructor with automatic memory and returns that A. new A("blah") on the other-hand calls the constructor with dynamic memory and returns a pointer to that A, ergo an A*. So your syntax A is not trying to invoke the move constructor, but another constructor like A(A*).
To move from an object referenced by a pointer, all you need to do is derefence and move:
A* a1 = new A("blah");
A a2(std::move(*a1));
There's nothing stopping you from defining a constructor like A(A*), but that shouldn't be needed and isn't recommended for using move semantics.
Also, your syntax B comments are incorrect; both are a value-constructor A("blah") followed by the move-constructor A(A&&); the std::move doesn't add anything here.
I often see the code that deletes 1)copy ctor and 2)assign ctor.
What is the advantage to do so?
I append sample code.
class A{
...
private:
A(const A& copy) = delete;
A &operator=(const A &assign) = delete;
};
It prevents the class from being copied or assigned.
For example it useful when you have a A class that has a m_p pointer as a member variable which that class owns (A class is responsible for deallocation). In this case you can't safely copy or assign the A class. Because compiler generated copy constructor and assign operator will share the ownership of that pointer and in destructor when you will want to delete pointer you can get
a double-delete or access violation from dereferencing a freed pointer.
If you have a case where you don't want to create copies of your class then you restrict that by making the copy constructor and assignment operator private or mark them as delete.
This is useful when you want to create a config class or a cache where having multiple copies of your class don't make sense.
In standard library, strems are not copy constructable and copy-assignable.
The rules for auto generating special move functions (constructor and assignment operator) in C++11 specify that no destructor can be declared. The logic is presumably that, if you need to do something special in destruction, that a move may not be safe.
However, for proper destructor calls in polymorphism, it is necessary to declare a base classes' destructor as virtual (otherwise deleting an instance of a sub class through a pointer of its base class will not properly chain the destructor).
I'm assuming, then, that even an empty destructor would prevent the compiler from automatically generating a special move functions. As in:
class Base {
virtual ~Base() { }
};
You can, however, default the destructor, as in:
class Base {
virtual ~Base() = default;
}
So question 1: Will this allow the compiler to auto generate special move functions?
There is a problem with the explicit default destructor, however. In at least the case of GCC 4.8.2, the signature is implicitly changed to noexcept. As in:
class Base {
virtual ~Base() = default; // compiler changes to:
// virtual ~Base() noexcept;
}
While I have no problem with noexcept in a destructor, this would break the following "client" code:
class Sub : public Base {
virtual ~Sub(); // this declaration is now "looser" because of no noexcept
}
So question 2 is more to the point: is there a way to allow auto generation of special move functions in C++11 and allow proper destructor chaining to sub classes (as described above), all without breaking subclass ("client") code?
No, a defaulted destructor is still considered user defined, so it will prevent the generation of move operations. Also declare the move operations default-ed to make the compiler generate them.
You need to only declare the move operations as default-ed in the base class. In the derived class, the destructor won't be user defined anymore (unless you explicitly say so), so the move operations won't be deleted.
So what I'd do is the following:
class Base
{
virtual ~Base() = default;
Base(Base&&) = default;
Base& operator=(Base&&) = default;
// probably need to think about copy operations also, as the move disables them
Base(const Base&) = default;
Base& operator=(const Base&) = default;
};
I highly recommend this talk by the person who contributed probably the most to the move semantics: http://www.slideshare.net/ripplelabs/howard-hinnant-accu2014
Or, if you can get your hands on, you should read the Item 17: Understand special member function generation from Scott Meyers' excellent book Effective Modern C++. This issue is excellently explained.
PS: I think you should think a bit more about your base classes. Most of the time, you should use abstract classes, so there will be no need to copy/move instances of them.
PSS: I think by default destructors are marked noexcept in C++11/14, so not explicitly specifying it shouldn't cause any problems:
Inheriting constructors and the implicitly-declared default
constructors, copy constructors, move constructors, destructors,
copy-assignment operators, move-assignment operators are all
noexcept(true) by default, unless they are required to call a function
that is noexcept(false), in which case these functions are
noexcept(false).
Following code does not compile with clang-700.1.81 and it's standard library:
#include <memory>
class something;
std::unique_ptr<something> external_function();
std::unique_ptr<something> local_function()
{
auto thing = external_function();
return thing;
}
The diagnostics by clang:
......./include/c++/v1/memory:2626:46: note: in instantiation of member function 'std::__1::unique_ptr.....requested here
_LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
^
test.cc:10:18: note: in instantiation of member function 'std::__1::unique_ptr<something, std::__1::default_delete<something> >::~unique_ptr' requested here
auto thing = external_function();
^
test.cc:4:7: note: forward declaration of 'something'
class something;
^
I guess it is trying to destroy the unique_ptr after copying it as return value, but is this really necessary? It is going be moved anyways, does it need to check if it can copy before realizing that it is easier to move it?
I could of course do this easily with a naked pointer.
Is there some other way to allow a uniqe_ptr to just "pass through" a translation unit, as shown in the example, without including extra header to get the definition of class something?
------EDIT--------
Also tried with GCC 5.3.0 and gnu libstdc++
Does not compile as well, with similar error messages.
------EDIT----
I think it is just trying to destroy the original thing object.
Thanks to Rudolf for the deleter idea ( a bit messy, but only option for this )
Looking at the library code I found this in unique_ptr's code:
if (__tmp)
__ptr_.second()(__tmp);
where second(_tmp) destructs the object pointed to. Even though it is never called, the compiler needs a definition to compile it. This is silly, but apparently gotta live with it.
From cppreference.com:
std::unique_ptr may be constructed for an incomplete type T, such as to facilitate the use as a handle in the Pimpl idiom. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr. (Conversely, std::shared_ptr can't be constructed from a raw pointer to incomplete type, but can be destroyed where T is incomplete).
Thus, with a custom deleter you can use a forward declared class if the full declaration is available for the deleter:
#include <memory>
class Foo;
class FooDeleter
{
public:
void operator()(Foo* pInstance);
};
std::unique_ptr<Foo, FooDeleter> pFoo;
class Foo
{
};
void FooDeleter::operator()(Foo* pInstance)
{
delete pInstance;
}
I know that the override contextual keyword was introduced to write safer code (by checking for a virtual function with the same signature) but I don't feel good about it, because it seems to be redundant for me to write override every time I want to override a virtual function.
Is it a bad practice to not use override contextual keyword for 99% of cases? Why/when should I have to use it (a compiler warning is not enough when we are hiding a virtual function mistakenly)?
EDIT: In other words; what is the advantage of using the override contextual keyword in C++11 while we always had a compiler warning if we were hiding a virtual function mistakenly in C++03 (without using override contextual keyword)?
The override keyword is totally useful and I would recommend using it all the time.
If you misspell your virtual function it will compile fine but at runtime the program will call the wrong function. It will call the base class function rather than your override.
It can be a really difficult bug to find:
#include <iostream>
class Base
{
public:
virtual ~Base() {}
virtual int func()
{
// do stuff for bases
return 3;
}
};
class Derived
: public Base
{
public:
virtual int finc() // WHOOPS MISSPELLED, override would prevent this
{
// do stuff for deriveds
return 8;
}
};
int main()
{
Base* base = new Derived;
std::cout << base->func() << std::endl;
delete base;
}
Annotations are what you call contextual keywords, they serve as clarification, to make sure anyone who reads the code realizes it is a function that overrides a function in a superclass or a interface.
The compiler can also give a warning if the originally overridden feature was removed, in which case you might want to think about removing your function as well.
As far as I know, nothing bad happens if you ommit anotations. It's neither right nor wrong. Like you stated correctly already: annotations are introduced to write safer code.
However: They won't change your code in any functional way.
If you work as a single programmer on your own project it might not matter wheter you use them or not. It is however good practice to stick to one style (i.e. either you use it, or you don't use it. Anything inbetween like sometimes using it and sometimes not only causes confusion)
If you work in a Team you should discuss the topic with your teammates and decide wheter you all use it or not.
What is the advantage of using override contextual keyword in C++11 while we always had a compiler warning if we were hiding a virtual function mistakenly
Nearly none!?
But:
It depends on how much warnings will be accepted by your build rules. If you say, every warning MUST be fixed, you will get the same result UNTIL you are using a compiler which give you the warning.
We have decided to always use override and remove virtual on overriding methods. So the "overhead" is zero and the code is portable in the meaning of "give an error" on misuse.
I personally like this new feature, because it makes the language clearer. If you say this is an override, it will be checked! And if we want to add a new method with different signature, we will NOT get a false positive warning, which is important in your scenario!