I have a class with some huge objects that I need to access in a const fashion. To do that I have the getABC() member function that copies these objects to the outside world. Is it possible to directly access them, since the copy operations are very slow in my case? shared_ptr would be preferable, and also I want to avoid making tuples just to return them in the getABC()
#include <iostream>
#include <vector>
using namespace std;
class foo {
private:
int a;
vector<int> b; // HUGE OBJECT
vector<int> c; // HUGE OBJECT
public:
foo(int a_, vector<int> b_, vector<int> c_) : a(a_), b(b_), c(c_) { }
void printfoo() {
cout << "a = " << a << endl;
cout << "b = ";
for(auto v:b) {
cout << v << " ";
}
cout << endl;
cout << "c = ";
for(auto v:c) {
cout << v << " ";
}
cout << endl;
}
void getABC(int & a_in, vector<int> & b_in, vector<int> & c_in ) const {
a_in = a;
b_in = b; // SLOW
c_in = c; // SLOW
}
};
int main() {
int in = 4;
vector<int> inA {1, 2, 3, 5};
vector<int> inB {2, 2, 3, 5};
foo bar(in, inA, inB);
bar.printfoo();
// GET THE MEMBERS
int out = 0;
vector<int> outA;
vector<int> outB;
bar.getABC(out, outA, outB);
// PRINT
cout << "OUT = " << out;
cout << "\nOUTA = ";
for(auto const &v : outA ) {
cout << v << " ";
}
cout << endl;
cout << "OUTB = ";
for(auto const &v : outA ) {
cout << v << " ";
}
cout << endl;
return 0;
}
I want to avoid making tuples just to return them in the getABC()
Why? It seems the most straightforward way to return references to multiple pieces of data:
tuple<const int&, const vector<int>&, const vector<int>&> getABC() const
{ return std::make_tuple(std::cref(a), std::cref(b), std::cref(c)); }
auto refs = bar.getABC();
for (auto& x : std::get<1>(refs))
// ...
Or create a named struct to return instead:
struct DataRefs {
int a;
const std::vector<int>& b;
const std::vector<int>& c;
};
DataRefs getABC() const { return { a, b, c }; }
This has the advantage that you don't need to use std::get<N>
to access the members, and can just use sensible names:
auto refs = bar.getABC();
for (auto& x : refs.b)
// ...
From your comment maybe you want something like this, but this would be a dumb interface:
void getABC(const int*& pa, const std::vector<int>*& pb, const std::vector<int>*& pc) const
{
pa = &a;
pb = &b;
pc = &c;
}
Which you could use like this:
int* a;
std::vector<int>* b;
std::vector<int>* c;
bar.getABC(a, b, c);
for (auto& x : *b)
// ...
As you can see, this is more verbose for the caller, and is just ugly and not idiomatic C++.
Or you could move the data into a separate sub-object:
class foo
{
struct data
{
int a;
std::vector<int> b;
std::vector<int> c;
};
data m_data;
public:
const data& getData() const { return m_data; };
};
auto& refs = bar.getData();
for (auto& x : refs.b)
// ...