C++ - Versus
Declarations vs Definitions
- Declaration: give it a name
- Definition: give it a name and all the info the compiler needs to create the code for that name
In C++ there is an important distinction between a declaration (“There is a class called Foo”) and a definition (“here is class Foo
including its members, methods, etc”). Since C++ attempts to be a language that can be compiled in a single pass, referring to an entity by name is an error if that entity hasn’t at least been declared at the point of that use. (Technically, a definition also counts as a declaration.)
// A forward declaration
class Foo;
struct vs class vs union
- struct: data members default to
public
. - class: data members default to
private
. - union: a special class type that can hold only one of its non-static data members at a time. (Similar to
oneof
in ProtoConf)
Google style guide suggests: "Use a struct only for passive objects that carry data; everything else is a class."
https://google.github.io/styleguide/cppguide.html#Structs_vs._Classes
moveable vs copyable
A movable type = can be initialized and assigned from temporaries.
A copyable type = can be initialized or assigned from any other object of the same type.
Copy behavior is defined by the copy constructor and the copy-assignment operator. E.g.
Move behavior is defined by the move constructor and the move-assignment operator.
class Foo {
public:
Foo(const Foo& arg); // copy constructor
Foo(Foo&& arg); // move constructor
Foo& operator=(const Foo& rhs); // copy assignment operator
Foo& operator=(Foo&& rhs); // move assignment operator
...
};
A copyable example:
class Foo {
public:
Foo(const Foo& other) = default;
Foo& operator=(const Foo& other) = default;
};
A move only example:
class Foo {
public:
// delete copy constructor and copy-assignment operator
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
// default move constructor and move-assignment operator
Foo(Foo&& other) = default;
Foo& operator=(Foo&& other) = default;
};
A non-copyable and non-movable example:
class Foo {
public:
// delete copy constructor and copy-assignment operator
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
// delete move constructor and move-assignment operator
Foo(Foo&& other) = delete;
Foo& operator=(Foo&& other) = delete;
};
Examples:
- movable but not copyable: e.g.
std::unique_ptr<int>
- movable and copyable:
int
andstd::string
, forint
, the move and copy operations are the same; forstd::string
, there exists a move operation that is less expensive than a copy.
Can be generated by the compiler, either implicitly or with = default
.
enum vs enum class
You can define enums in 2 different ways: enum
or enum class
. Prefer enum class
, since it create its own scope, and doesn't pollute the namespace that it is in. In comparison, an enum
just spills its contents into the enclosing scope.