I can achieve the functionality I need using option 3, however I would like to investigate whether it is possible to create the array on the stack instead.
#include <array>
#include <vector>
struct NotDefaultConstructable
{
NotDefaultConstructable(int val){};
};
int main()
{
//std::array<NotDefaultConstructable, 5> aA; // Fails to compile. [On stack]
//std::vector<NotDefaultConstructable> aV(5); // Fails to compile. [On heap]
std::vector<NotDefaultConstructable> aV; // Compiles. [ On heap]
aV.reserve(5);
}
std::array is an aggregate class type which may have a trivial, implicitly defaulted constructor. If T is not default-constructible, the implicit default constructor is defined as deleted, as per [class.ctor]/5.3.
As this applies in your case, you cannot construct an object of std::array<NotDefaultConstructable, 5> by default construction. You can, however, construct it by means of aggregate initialization:
#include <array>
struct NotDefaultConstructable {
NotDefaultConstructable(int){};
};
int main() {
std::array<NotDefaultConstructable, 3> arr{1, 2, 3};
}
In this sense, all elements of a std::array object should arguably be initialized, even if they represent a non-present object (yet to be "filled", if you will).
You could either find a an appropriate static vector container, such as boost::static_vector, or you could e.g. implement a thin wrapper around std::array which stores an array as above as well its runtime size. Another alternative would be to use a std::array of optionals:
#include <array>
#include <iostream>
#include <optional>
struct NotDefaultConstructable {
NotDefaultConstructable(int val) : val_(val) {};
int val_;
};
int main() {
std::array<std::optional<NotDefaultConstructable>, 3> arr{};
arr[1] = NotDefaultConstructable{42};
for(const auto& element : arr) {
if(element.has_value()) {
std::cout << "has value: " << element.value().val_;
} // has value: 42
}
}
where no dynamic memory allocation takes place (cppreference):
If an optional contains a value, the value is guaranteed to be allocated as part of the optional object footprint, i.e. no dynamic memory allocation ever takes place.
Judging by the fact that OP mentioned looking into using placement new, I wanted to make a full example of using a stack allocated array as memory for dynamically constructed objects.
Using this method, you can allocate stack memory without initializing it with instances. The problem, however, is that you have to monitor the object lifetime for each instance yourself. In this example, I construct all of them and can then simply assume that all of them have to be destroyed, however monitoring how many instances are alive and should be destroyed is quite messy.
This is why dfrib's answer is much more suitable in your situation, as it allows you to allocate the memory on the stack using std::array<std::optional<Type>, 5> and assign instances later. Object lifetime will also be managed for you, so is much more advisable.
Example 1: Placement New:
#include <array>
#include <iostream>
struct NotDefaultConstructable {
int Value;
NotDefaultConstructable(int val) : Value(val) {
std::cout << "constructed: " << Value << "\n";
};
~NotDefaultConstructable(){
std::cout << "destructed: " << Value << "\n";
}
};
int main() {
// allocate enough memory on the stack for 5 instances
char aV[sizeof(NotDefaultConstructable) * 5];
// get a pointer to the first NotDefaultConstructable in that array
auto avArray = static_cast<NotDefaultConstructable*>(static_cast<void*>(&aV[0]));
// use placement new to construct each instance
for (auto i = 0; i < 5; ++i)
new (&avArray[i]) NotDefaultConstructable((i + 1) * 2);
// do stuff with the instances
for (auto i = 0; i < 5; ++i)
std::cout << "instance: " << avArray[i].Value << "\n";
// destruct them all manually, this is what makes placement new a little
// cumbersome. I would advise to use std::optional instead.
for (auto i = 0; i < 5; ++i)
avArray[i].~NotDefaultConstructable();
}
example 1: https://godbolt.org/z/7jW8Pb
Example 2: std::array with std::optional
Here's an example using std::optional, which has minor overhead (about ~4 bytes per object) to achieve much more convenience:
#include <array>
#include <optional>
#include <iostream>
struct NotDefaultConstructable {
int Value;
NotDefaultConstructable(int val) : Value(val) {
std::cout << "constructed: " << Value << "\n";
};
~NotDefaultConstructable(){
std::cout << "destructed: " << Value << "\n";
}
};
int main() {
// allocate enough memory on the stack for 5 instances
std::array<std::optional<NotDefaultConstructable>, 5> avArray;
// use placement new to construct each instance
for (auto i = 0; i < 5; ++i)
avArray[i] = NotDefaultConstructable((i + 1) * 2);
// do stuff with the instances
for (auto i = 0; i < 5; ++i)
std::cout << "instance: " << avArray[i].value().Value << "\n";
}
example 2: https://godbolt.org/z/Ynx8aE
You can try the following
#include <iostream>
struct NotDefaultConstructable {
NotDefaultConstructable(int val) {
};
};
int main() {
NotDefaultConstructable aV[5] { 6, 6, 6, 6, 6 };
}
Related
If I have a class with members like this:
class MyClass {
public:
void set_my_vector() {
for (int ind = 0; ind < 3; ++ind) {
my_vector.push_back(new MyStruct(i, i*2));
}
}
private:
struct MyStruct {
int num_a;
int num_b;
MyStruct(int i, int j) : num_a(i), num_b(j) {}
};
std::vector<MyStruct*> my_vector;
};
Do I need to write the rule-of-five functions, or will std::vector take care of deep copying and deleting the elements allocated on the heap?
EDIT:
The following code uses default copy constructor, so I assume that after I copy my_class1 object into my_class2 object, the elements of my_class1.my_vector and my_class2.my_vector will be the same, because the MyStruct pointers were copied, but not the data itself. However, the output shows that they are not the same. You can run the code here: https://onlinegdb.com/S1pK9YE4v
#include <iostream>
#include <vector>
class MyClass {
public:
void fill_my_vector(int i, int j) {
my_vector.clear();
for (int ind = 0; ind < 3; ++ind) {
my_vector.push_back(new MyStruct(i, j));
}
}
void print () {
for (int ind = 0; ind < 3; ++ind) {
std::cout << my_vector[ind]->int1 << ", " << my_vector[ind]->int2 << std::endl;
}
std::cout << std::endl;
}
private:
struct MyStruct {
MyStruct (int i, int j) :
int1(i), int2(j)
{}
int int1;
int int2;
};
std::vector<MyStruct*> my_vector;
};
int main()
{
MyClass my_class1;
my_class1.fill_my_vector(42, 43);
std::cout << "my_class1: " << std::endl;
my_class1.print();
MyClass my_class2 = my_class1;
my_class2.fill_my_vector(12, 13);
std::cout << "my_class2: " << std::endl;
my_class2.print();
std::cout << "my_class1: " << std::endl;
my_class1.print();
}
EDIT2: I know about smart pointers. I am specifically interested what happens if I use raw pointers.
You need to implement the copy constructor, copy assignment and destructor.
Additionally, consider changing your vector declaration from
std::vector<MyStruct*> my_vector;
to
std::vector<std::unique_ptr<MyStruct>> my_vector;
so that it actually owns the heap allocated objects properly. Doing this change will help you not write a destructor.
No, std::vector doesn't take care of deep copying of your objects stored by pointer. You have few possibilities to solve this:
Store MyStruct by value.
Store std::unique_ptr<MyStruct>.
Store std::shared_ptr<MyStruct>.
Note that because MyStruct contains only fields of the primitive types, neither of copy constructor, assignment operator and destructor are needed, otherwise you'd have to implement them, default implementation which compiler will generate automatically will be good enough.
I have a struct Foo;
typedef struct {
int bar;
char baz;
} Foo;
Suppose I then declare an array of Foo as;
Foo* arr = new Foo[300];
And proceed to initialize every member with a loop. I would like very much to be able to get an array of all members bar;
int* barr_arr = ...
What is the most efficient way to do this? Is there some way to exploit the memory layout such that I need not loop over the entire Foo array?
Since we know the memory layout in advance could we exploit the fact that we know the address of every member if we're clever about alignment?
What is the most efficient way to do this? Is there some way to exploit the memory layout such that I need not loop over the entire Foo array?
I don't think there is away to do that without looping. You can simplify your code by using std::transform but std::transform does loop.
Also, I would recommend using std::vector instead of allocating an array using new.
std::vector<Foo> arr(300);
....
std::vector<int> bArr(arr.size());
std::transform(arr.begin(), arr.end(), bArr.begin(), [] -> (Foo const& f) { return f.bar; });
When you are initializing the first array, you can grab a pointer to the field inside each element and store that in a separate array.
struct Foo
{
int bar;
float baz;
};
const int SIZE = 5;
Foo foos[SIZE];
int *bars[SIZE];
for(int c = 0; c < SIZE; c++) {
foos[c].bar = c;
foos[c].baz = c;
bars[c] = &foos[c].bar; // Grab pointer to field
}
for(int c = 0; c < SIZE; c++) {
std::cout << "Bar Value: " << *bars[c] << std::endl;
}
If Foos typically exist in arrays, and corresponding arrays of bars and bazs often need to be accessed, I would suggest redesigning your data structures to better suit your problem. Obviously, we're not reading the code that inspired this question, but given the information provided, I might suggest something like:
struct FooArray {
int* bars;
char* bazes;
size_t n_elements;
};
This removes the need to allocate a new buffer for the bar array, which, depending on how many Foos are being processed, might entail significant memory savings.
I would also note that, if you're not working at a low level and don't actually need an int* but can do with a std::vector<int>, then #R Sahu's answer is likely a more appropriate solution.
The goal drives the design.
If your main use is to pass all bar members in a row, same for baz members, then create separate containers:
std::vector<int> bar;
std::vector<char> baz;
Then passing bar as an array is straightforward: just use bar.data().
If you add a constructor to your Foo that takes the size of array, you could have only one object of Foo. You can then make it that you can access either the whole vector data or individual elements with subscript:
#include <iostream>
#include <vector>
#include <memory>
struct Foo
{
std::vector<int> bars;
std::vector<char> bazs;
std::size_t size;
Foo(size_t size, int bar = 0, char baz = 0) :
bars(size, bar), bazs(size, baz), size{size}
{
}
auto operator[](size_t n)
{
// if (n >= size) ...
struct
{
int &bar;
char &baz;
} temp{ bars[n], bazs[n] };
return temp;
}
};
int main()
{
Foo arr(30, 100, 'a'); // 30 items
std::cout << arr[29].bar << std::endl;
std::cout << arr[29].baz << std::endl;
std::cout << arr.bars[29] << std::endl;
std::cout << arr.bazs[29] << std::endl;
std::unique_ptr<Foo> arr2 = std::make_unique<Foo>(25, 10, 'b'); // 25 items
std::cout << arr2->operator[](15).bar << std::endl;
std::cout << arr2->operator[](15).baz << std::endl;
arr2->bars[15] = 11;
std::cout << arr2->bars[15] << std::endl;
arr2->bazs[15] = 'c';
std::cout << arr2->bazs[15] << std::endl;
return 0;
}
Demo: https://ideone.com/TiVwOT
100
a
100
a
10
b
11
c
How can you initialize a container to a class with no default? How can you create the array of pointers required without using new or a method which calls the default constructor of a class?
#include <string>
#include <iostream>
#include <vector>
#include "MyVector.h"
class NoDefault {
public:
//NoDefault():value(0){};
NoDefault(const int& value) : value(value) {}
int value;
};
std::ostream& operator<<(std::ostream& out, const NoDefault& noDefault) {
out << noDefault.value;
return out;
}
int main() {
MyVector<int> intVec(10, 99);
MyVector<std::string> stringVec(5, "hi");
MyVector<NoDefault> noDefaultVec(4, -3);
std::vector<std::vector<std::string>> tempRealVec({{"hi", "bye"}, {"sly",
"guy", "why"}});
MyVector<MyVector<std::string> > tempMyVec(tempRealVec);
MyVector<MyVector<MyVector<std::string> > > vecVecVecStringVec(2, tempMyVec);
std::cout << "intVec = " << intVec << std::endl;
std::cout << "stringVec = " << stringVec << std::endl;
std::cout << "noDefaultVec = " << noDefaultVec << std::endl;
std::cout << "vecVecVecStringVec = " << vecVecVecStringVec << std::endl;
std::cout << "hello" << std::endl;
return 0;
}
This is the constructor
template <typename T>
MyVector<T>::MyVector(const unsigned int& numElements,const T& value):data_(new
T[numElements]),size_(numElements)
{
for(int i = 0; i < size_; i++)
{
if(std::is_same<T,int>::value)
data_[i]=T(value);
else if(std::is_same<T,std::string>::value)
data_[i]=T(value);
else if(std::is_same<T,MyVector>::value)
data_[i]=T(value);
else if(std::is_same<T,NoDefault>::value)
data_[i]=T(value);
}
}
the error thrown because of the use of new in initializer list is no matching function for call to NoDefault::NoDefault(), even if i create that constructor, which would defeat the purpose. It then prints the vector with the default value not the value given as the second argument in the call to MyVector.
You can use placement new. Placement new allows you to construct an object in a specific memory location, so the steps look something like this:
Allocate raw memory (malloc or ::operator new both work)
Construct your object in this raw memory (new (ptr) NoDefault{args})
This is roughly how regular new works (allocates memory via ::operator new, then uses placement new to construct the object). I'm not sure if stdl containers like vector are required to use this method, but I'd be a bit surprised if they didn't.
The big caveat (and it is a big one) is that when using placement new you have to manually invoke the destructor (the only time I'm aware of where you intentionally invoke destructors). After the destructors have been called, you're free to release the allocated memory using the appropriate method (e.g., free or ::operator delete).
More information is available from the C++ FAQ.
I have some code that claims ownership of a sequence of raw pointers, and am wondering if there is an acceptable way to do this? What I'm looking for is a way to enforce the ownership in code to a greater degree. Mainly, I've been wondering whether or not my constructor should be taking a vector of unique pointers directly.
As a sidenote, once ownership has been claimed, the data is supposed to be immutable.
The code follows roughly the pattern of class X below.
#include <iostream>
#include <memory>
#include <vector>
using namespace std; // For readability purposes only
class X {
public:
const vector< unique_ptr<const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (vector<int*> rawData)
: data { make_move_iterator(rawData.begin()), make_move_iterator(rawData.end()) }
{ }
};
int main() {
// Illustrating some issues with claiming ownership of existing pointers:
vector<int*> rawData { new int(9) , new int(4) };
int* rawPointer = rawData[0];
{ // New scope
X x(rawData);
cout << *(x.data[0]) << endl; // Unique pointer points to 9
*rawPointer = 7;
cout << *(x.data[0]) << endl; // Unique pointer points to 7
}
cout << *rawPointer << endl; // The pointer has been deleted, prints garbage
return 0;
}
It is difficult to post an answer without detailed knowledge of your situation. But my recommendation is to attach your data to a unique_ptr as soon as it is known. Then you can move that unique_ptr into and out of vectors at will. For example:
#include <iostream>
#include <memory>
#include <vector>
using namespace std; // For readability purposes only
class X {
public:
const vector< unique_ptr<const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (vector<unique_ptr<const int>>&& v)
: data { std::move(v) }
{ }
};
vector<unique_ptr<const int>>
collectRawData()
{
auto rawData = {9, 4};
vector<unique_ptr<const int>> data;
for (auto const& x : rawData)
data.push_back(make_unique<int>(x));
return data;
}
int main() {
auto rawData = collectRawData();
{ // New scope
X x(std::move(rawData));
cout << *(x.data[0]) << endl; // Unique pointer points to 9
cout << *(x.data[1]) << endl; // Unique pointer points to 4
}
}
You did several misstakes.
In case of const vector< unique_ptr<const int> > data; a move iterator does make not that much sense. The reason why is, int* doesn't have a move constructor.
If you call X's constructor X (vector<int*> rawData) with vector < int* > so the copy constructor of vector < int* > gets called, but that's not what you want to.
Btw. the reason why to use move is, to avoid big memory copies. For instance std::vector < int* >: The member attribute size and the pointer to the memory location where your int*s are stored of std::vector<int*> must be copied by a move too but not the int*s self. A conclusion is that move is there to claim ownership.
If you want shared pointers like that, use std::shared_ptr. It owns a counter, which counts the ptrs which pointing to itself.
´
My Example Code:
class X
{
public:
const std::vector< std::shared_ptr< const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (std::vector<std::shared_ptr<int>>& rawData)
//: data(rawData)
: data(rawData.cbegin(), rawData.cend())
{ }
};
int main() {
// Illustrating some issues with claiming ownership of existing pointers:
std::vector<std::shared_ptr<int>> rawData { std::make_shared<int>(9), std::make_shared<int>(4) };
int* rawPointer = rawData[0].get();
{ // New scope
X x(rawData);
cout << *(x.data[0]) << endl; // Unique pointer points to 9
*rawPointer = 7;
cout << *(x.data[0]) << endl; // Unique pointer points to 7
}
cout << *rawPointer << endl; // The pointer has been deleted, prints not more garbage
return 0;
}
If you dont want use std::shared_ptr, you will need an GC.
I know that in general the life time of a temporary in a range-based for loop is extended to the whole loop (I've read C++11: The range-based for statement: "range-init" lifetime?). Therefore doing stuff like this is generally OK:
for (auto &thingy : func_that_returns_eg_a_vector())
std::cout << thingy;
Now I'm stumbling about memory issues when I try to do something I thought to be similar with Qt's QList container:
#include <iostream>
#include <QList>
int main() {
for (auto i : QList<int>{} << 1 << 2 << 3)
std::cout << i << std::endl;
return 0;
}
The problem here is that valgrind shows invalid memory access somewhere inside the QList class. However, modifying the example so that the list is stored in variable provides a correct result:
#include <iostream>
#include <QList>
int main() {
auto things = QList<int>{} << 1 << 2 << 3;
for (auto i : things)
std::cout << i << std::endl;
return 0;
}
Now my question is: am I doing something dumb in the first case resulting in e.g. undefined behaviour (I don't have enough experience reading the C++ standard in order to answer this for myself)? Or is this an issue with how I use QList, or how QList is implemented?
Since you're using C++11, you could use initialization list instead. This will pass valgrind:
int main() {
for (auto i : QList<int>{1, 2, 3})
std::cout << i << std::endl;
return 0;
}
The problem is not totally related to range-based for or even C++11. The following code demonstrates the same problem:
QList<int>& things = QList<int>() << 1;
things.end();
or:
#include <iostream>
struct S {
int* x;
S() { x = NULL; }
~S() { delete x; }
S& foo(int y) {
x = new int(y);
return *this;
}
};
int main() {
S& things = S().foo(2);
std::cout << *things.x << std::endl;
return 0;
}
The invalid read is because the temporary object from the expression S() (or QList<int>{}) is destructed after the declaration (following C++03 and C++11 §12.2/5), because the compiler has no idea that the method foo() (or operator<<) will return that temporary object. So you are now refering to content of freed memory.
The compiler can't possibly know that the reference that is the result of three calls to operator << is bound to the temporary object QList<int>{}, so the life of the temporary is not extended. The compiler does not know (and can't be expected to know) anything about the return value of a function, except its type. If it's a reference, it doesn't know what it may bind to. I'm pretty sure that, in order for the life-extending rule to apply, the binding has to be direct.
This should work because the list is no longer a temporary:
#include <iostream>
#include <QList>
int main() {
auto things = QList<int>{};
for (auto i : things << 1 << 2 << 3)
std::cout << i << std::endl;
return 0;
}
And this should work because the binding is direct, so the rule can apply:
#include <iostream>
#include <QList>
int main() {
for (auto i : QList<int>{1, 2, 3})
std::cout << i << std::endl;
return 0;
}