vector of class without default constructor
How can I create a
std::vector
of typeA
and give an argument toA
's constructor?
std::vector<A> v1(10, 42); // 10 elements each with value 42
std::vector<A> v2{1,2,3,4}; // 4 elements with different values
How would I add 3 to the vector?
v.emplace_back(3); // works with any suitable constructor
v.push_back(3); // requires a non-explicit constructor
The lack of a default constructor only means you can't do operations that need one, like
vector<A> v(10);
v.resize(20);
both of which insert default-constructed elements into the vector.
Vector of objects without a default constructor and iterator
This range based loop is making copies:
for (auto i: c) {
cout << i << endl;
}
And the copy constructor initializes v
to 4
(and does not make a copy):
Custom(const Custom &) : v{4} {
}
You can either implement a proper copy constructor or use references in the loop to get the desired output:
for (const auto& i: c) {
cout << i << endl;
}
I would suggest to do both, because this copy constructor is not doing a copy by any means. The compiler generated copy constructor should be fine:
Custom(const Custom &) = default;
PS: The fact that Custom
has a deleted default constructor is not really relevant for the posted code. Nowhere in the code a Custom
is default constructed. Also there is no iterator in your code. In the range based loop i
is a copy/reference of the elements in the vector, it is not an iterator.
How can I initialize an std::array of a class without a default constructor?
With copy constructor, something along these lines:
template <typename T, size_t... Is>
std::array<T, sizeof...(Is)> MakeArrayHelper(
const T& val, std::index_sequence<Is...>) {
return {(static_cast<void>(Is), val) ...};
}
template <typename T, size_t N>
std::array<T, N> MakeArray(const T& val) {
return MakeArrayHelper<T>(val, std::make_index_sequence<N>{});
}
std::array<Foo, 100> arr = MakeArray<Foo, 100>(Foo(5));
Actually, this can be done without copy constructor after all. This solution relies heavily on C++17's mandatory copy elision.
template <typename T, size_t... Is, typename... Args>
std::array<T, sizeof...(Is)> MakeArrayHelper(
std::index_sequence<Is...>, Args&&... args) {
return {(static_cast<void>(Is), T{std::forward<Args>(args)...}) ...};
}
template <typename T, size_t N, typename... Args>
std::array<T, N> MakeArray(Args&&... args) {
return MakeArrayHelper<T>(std::make_index_sequence<N>{},
std::forward<Args>(args)...);
}
Demo
std::vector works with classes that are not default constructible?
The requirement in C++03 is that types being stored in a container be CopyConstructible
and Assignable
(see §23.1 Container Requirements). However, in C++11 these requirements are relaxed, and tend to apply to the operations performed on the container. So a simple default construction has no requirements (see teble 96, §23.1 in C++11 standard).
As soon as you try to copy a vector, or insert elements into it, you will meet the CopyInsertable
, CopyAssignable
, EmplaceConstructible
, MoveInsertable
, MoveAssignable
etc. requirements
Is there still a need to provide default constructors to use STL containers?
This quote is from the C++ Programming Language, Special edition , 2005 by Bjarne Stroustrup in section 16.3.4:
If a type does not have a default constructor, it is not possible to create a vector with elements of that type, without explicitly providing the value of each element.
So it was indeed a standard requirement. It was also required that (section 17.1.4) :
To be an element of a container, an object must be of a type that allows the container implementation to copy it. The container may copy it using a copy constructor or an assignment; in either case the result of the copy must be an equivalent object.
So yes, there were "official" constructor requirementsand the library implementation were supposed to be interchangeable and not add other requirements. (Already in the very first proposal for STL in 1995, the authors tried as much as possible to clearly indicate specifications and narrow down the implementation dependent flexibility.)
You therefore had to provide a default constructor in the case where you declared other constructors:
If a user has declared a default constructor, that one will be used; otherwise, the compiler will try to generate one if needed and if the user hasn't declared other constructors.
Nowadays, this requirement is relaxed. Since C++11:
The requirements that are imposed on the elements depend on the actual operations performed on the container.
So you can define a vector for a class without default constructor, if it doesn't make sense. This for example perfectly works (online demo):
class MyClass {
public:
MyClass(int x) {}
};
int main() {
vector<MyClass> v;
MyClass test{1};
v.push_back(test);
}
But it works only as long as you don't use any operation that would need the default constructor. For instance v.resize(6);
would fail to compile.
stl vector and c++: how to .resize without a default constructor?
Use the 2-argument overload:many_things.resize(20, something(5));
No default constructor exists for class if I want to construct a class with another one
The problem is that since you have a parameterized constructor for your class Ball
, the compiler will not synthesize a default constructor by itself. So if you want to create/construct an object of class Ball
using a default constructor, say by writing Ball b;
, then you must first provide a default constrcutor for class Ball
as shown below.
Solution 1
Just add a default constrctor in class Ball
as shown below:
Ball.h
class Ball {
private:
Vector3 position;
Vector3 speed;
float radius = 0;//use in-class initializer
public:
Ball(Vector3 ballPosition, Vector3 ballSpeed,float ballRadius);
Ball() = default; //DEFAULT CONSTRUCTOR ADDED
};
Alternative Method of adding constructor
Another way of adding a default constructor would be as shown below:
Ball.h
#pragma once
#include <vector>
#include <raylib.h>
class Ball {
private:
Vector3 position;
Vector3 speed;
float radius = 0;//use IN-CLASS INITIALIZER
public:
Ball(Vector3 ballPosition, Vector3 ballSpeed,float ballRadius);
Ball(); //declaration for default constrctor
};
Ball.cpp
#include "Ball.h"
#include <raymath.h>
#include <rlgl.h>
Ball::Ball(Vector3 position, Vector3 speed,float radius) {
this->position = position;
this->speed = speed;
this->radius = radius;
}
//define the default constructor
Ball::Ball()
{
cout << "default constructor" << endl;
//do other things here if needed
}
Related Topics
What Is Default Storage Class for Global Variables
Memoized, Recursive Factorial Function
Mingw Error: 'Thread' Is Not a Member of 'Std'
Why There Is No Std::Copy_If Algorithm
Should You Overload Swap in the Std Namespace
What Is the Practical Use of Pointers to Member Functions
Why Does (I|O)Fstream Take a Const Char* Parameter for a File Name
Std::Vector Calling Destructor Multiple Times During Push_Back
How to Mark a Struct Template as Friend
How to Statically-Initialize a Dynamically-Allocated Array in C++
Template Base Constructor Call in Member Initialization List Error