I want to have class scope alias to the vector from an argument.
For exapmale:
class Solution {
private:
vector<int> b; // I want that &b = a, where a from function solve
int f(int i) {
// here I want to use vector<int> a,
// not passing it as a function argument every time
}
public:
int solve(vector<int>& a) {
// here I want to do smth like b = a; which works for O(1)
}
};
Unfortunatelly, I can't just declare vector<int> &b; , because of the error:
declaration of reference variable 'b' requires an initializer
Could you please, explain how to do it in C++11/14?
Update: I can't change the declaration of int solve(vector<int>& a), the interface provided from outside.
Update: I've changed the code to the more explicit. Looks like I shouldn't do again because in answers and comments people use original variable names. I'm sorry, don't have much experience with StackOverflow.
Maybe this?
class Solution {
public:
vector<int> a;
int maxCoins(const vector<int>& _a) { // const because copying
a.assign( _a.begin(), _a.end() );
}
};
But know that you can also do this if you want a reference to the original vector<int> rather than a copy:
class Solution {
public:
vector<int> & a;
int maxCoins(vector<int>& _a) : a( _a ) {}
};
Update
This is probably closest. You cannot re-initialize a reference, but then this is exactly the use-case for pointers.
class Solution {
public:
vector<int> * a;
int f(int i) {
a->size(); // can access indirectly
(*a)[1]; // element access is slightly trickier
vector<int> & _a = *a; // or can create a direct ref
_a.size();
}
int solve(vector<int>& _a) {
a = &_a; // store address to _a. a reference is like any local variable unless doing something funny
}
};
Update 2 - using no pointers
#include <functional>
class Solution {
public:
// vector<int> a;
typedef vector<int> datatype;
datatype blankref;
std::reference_wrapper<datatype> a = blankref;
int f(int i) {
vector<int> & _a = a;
}
int solve(vector<int>& _a) {
a = std::ref(_a);
}
};
You can't avoid the fact that references are assign-once. References in a class instance have to be assigned using initializer syntax. To have a re-usable reference, you need to have a newly initialized object each time.
To help us here, thanks to advice in comments, there is std::reference_wrapper<T> type that can hold instances of references. It can be assigned to using std::ref( _a ) repeatedly.
Honestly pointers are not inelegant when used right, imo. It comes down to use case and what you believe you would need. Performance wise this probably won't be as good as with pointers (because of temporary objects being constructed), though no guarantees... it should perform similarly in any case.
Related
I have to do a function in c++ that returns 2 arrays by passing them from reference.
I have no idea and it seems noone also has.
Would you be so kind to write an exemple for me?
I thaught to do
int *vettore=new int[5];
return vettore
buy it only returns one.
Tnx in advance.
Let's forget about arrays for a second, because that is another bag of problems. Let's concentrate on returning two simple types, e.g. returning two integers.
Obviously this won't work (because... not python):
int, int foo()
{
int a = ...
int b = ...
return a, b;
}
So what options are you left with if you want to return multiple values in C++?
Option 1. Return a class
You can "bundle" your values in a class, either create a new class for them if that makes sense, or simply use std::pair or std::tuple:
std::pair<int, int> foo()
{
int a = ...;
int b = ...;
return {a, b}
}
Option 2. Use "out" parameters.
You can pass parameters by reference, thus being able to modify from within the function objects from outside. E.g.:
void foo(int& a, int& b)
{
a = ...;
b = ...;
}
I think this is what you teacher meant by "pass by reference".
Ok, what about arrays?
This is tricky to answer because it is not clear what you mean by arrays and some of the meanings are discouraged.
I will start from the most recommended, to what is considered bad practice and even wrong:
std::vector
The defacto type for representing arrays in C++ should always be std::vector. Thus your requirement of returning by reference could mean:
void foo(std::vector<int>& v1, std::vector<int&>& v2);
std::array
Alternately if the size of the array is known at compile time:
void foo(std::array<int, 24>& a1, std::array<int, 24>& a2);
C pointers
Ok, now we are in the discouraged territory. Don't do this, unless to appease an unreasonable teacher or curriculum:
void foo(int* &v1, int* &v2)
{
v1 = new int[11];
v2 = new int[24];
...
}
C arrays
void foo(int (&a)[11], int (&a2)[24]);
You could do this:
return std::make_pair(array1,array2);
You'll need to #include <utility>
To access the arrays use pair.first or pair.second
example:
#include <utility> //std::pair
#include <iostream> //std::cout
std::pair<int*,int*> returnpair(){
int arr1[3] = {1,2,3};
int arr2[3] = {4,5,6};
return std::make_pair(arr1,arr2);
}
int main(){
std::pair<int*,int*> pair= returnpair();
std::cout<<pair.first[1]; //access 2nd member of arr1
}
Output:
2
Reference:
http://www.cplusplus.com/reference/utility/pair/
You can do that by returning a struct node pointer which is acceptable in C/C++.
Following is the sample code of node :
struct node {
int a[100];
int b[100];
};
Coming to the function :
struct node* fun() {
struct node* ptr;
// write your code
return ptr;
}
In main : you can access the arrays as follows :
struct node* ptr=fun();
ptr->a // is the first array
ptr->b // is the second array
Hope it helps
I have a question, its a bit hard to discribe it so be easy on me please.
I have two classes, A and B, class A have a private member- vector:
class A
{
private:
struct complex
{
int x;
vector< int > y;
};
vector< complex > m_resultVector; // <---- the private member
public:
void getPointerToVector( vector< complex >::iterator it )
{
it = m_resultVector.begin();
}
};
I need to get access (only read) from class B, to this m_resultVector;, I could write a get function but m_resultVector is very long vector and I don't want to copy the entire vector to a new one, I want to send its pointer. also the important part- I need class B cannot change the content of m_resultVector
class B
{
struct complex
{
int x;
vector< int > y;
};
void functionOf_B()
{
A class_A;
vector< complex >::iterator p_resultVector;
class_A.getPointerToVector(p_resultVector); // <------ compilation error here
// some reading from the content of p_resultVector
}
};
when I try to compile it, I get the error:
cannot convert parameter 1 from 'std::_Vector_iterator<_Myvec>' to
'std::_Vector_iterator<_Myvec>'
so basically, I have to questions-
why do I get this error? the complex struct is defined in both classes.
where and how do I need to declare on const iterator on class B, so it will be read only? I'm not sure ...
That is because A::complex and B::complex are different types (with same content, but that does not matter). So that vector<A::complex> and vector<B::complex> are different. Move definition of struct complex outside A and B.
Also there are more issues in your code. A::getPointerToVector does nothing, because it copies input vector iterator to temporary one, assigns a value to it and after return from that function, everything is lost. Using this approach, you would have to pass vector<complex>::iterator as reference (thus vector<complex>::iterator&).
I would rather write a method in A like this
const vector<complex>& get_vector() const
{
return m_resultVector;
}
I this way, you can doo this.
void foo()
{
A class_A;
// do something with A
const vector<complex>& p_result = class_A.get_vector();
// now you are holding whole vector and you can call methods
// defined as const (which does not modify that vector)
p_result.begin();
p_result.at(0);
p_result.end();
}
Zereges solution seems good. But I understand you do not want to return vector. I could not come up with any solution other than below.
In Class A:
void getPointerToVector(int position, int &var,vector<int>& o_Vec)
{
vector<complex>::iterator itr;
complex c;
c = m_resultVector.at(position);
var = c.x;
o_Vec = c.y;
}
In class B :
void functionOf_B()
{
A class_A;
int aVar;
std::vector<int> vec;
class_A.getPointerToVector(2, aVar, vec);
// some reading from the content of p_resultVector
}
I am not sure how efficient and complex this is. I would suggest better to use Zereges solution
I'm refactoring a class for my project to adapt int data. The code is quite complicated, try to give a simple example below:
struct A {
A(int a):a_(a) {} // Supports implicit conversion from int
int a_;
};
void print(A a) { cout<<a.a_<<endl; }
void x2(A *a) { // change a's value
a->a_ *= 2;
}
int main() {
int b = 2;
print(b); // pass int as A without any problem
x2(&b); // pass int* as A* - failed
cout<<b<<endl; // b is supposed to changed by x2()
}
In this case maybe template is a good choice, but I'm afraid rewritting the whole class with template would be a huge effort and would do a little harm to the readablity especially for my colleagues.
Is there any other way to use "int*" as "A*"?
No, there's no "way". What you are trying to do here is violating the contract on x2, which is that a will be a valid pointer to A.
The simplest change to it would be to change x2 to:
(There's really no need to use a pointer here)
void x2 (A& a) {
a.a_ *= 2;
}
And then call it with A value that's wrapped around the int (like #jrok suggested):
A a(2);
x2(a);
If you are conderned with printing, provide operator<< for A.
Is there a standard container for a sequence of fixed length, where that length is determined at runtime. Preferrably, I'd like to pass an argument to the constructor of each sequence element, and use that argument to initialize a const member (or a reference). I'd also like to obtain the sequence element at a given index in O(1). It seems to me that all of my requirements cannot be met at the same time.
I know std::array has fixed length, but that length has to be known at compile-time.
std::vector has dynamic size, and allows passing contructor arguments using emplace. Although you can reserve memory to avoid actual reallocations, the type still has to be movable to theoretically allow such reallocations, which e.g. prevents const members.
Then there is std::list and std::forward_list, which don't require a movable type, but which are still resizable and will perform rather poorly under random-access patterns. I also feel that there might be considerable overhead associated with such lists, since each list node will likely be allocated separately.
Strangely enough, std::valarray is my best bet so far, since it has a fixed length and won't resize automatically. Although there is a resize method, your type won't have to be movable unless you actually call that method. The main deficit here is the lack for custom constructor arguments, so initializing const members isn't possible with this approach.
Is there some alternative I missed? Is there some way to adjust one of the standard containers in such a way that it satisfies all of my requirements?
Edit: To give you a more precise idea of what I'm trying to do, see this example:
class A {
void foo(unsigned n);
};
class B {
private:
A* const a;
const unsigned i;
public:
B(A* aa) : a(aa), i(0) { }
B(A* aa, unsigned ii) : a(aa), i(ii) { }
B(const std::pair<A*, unsigned>& args) : B(args.first, args.second) { }
B(const B&) = delete;
B(B&&) = delete;
B& operator=(const B&) = delete;
B& operator=(B&&) = delete;
};
void A::foo(unsigned n) {
// Solution using forward_list should be guaranteed to work
std::forward_list<B> bs_list;
for (unsigned i = n; i != 0; --i)
bs_list.emplace_front(std::make_pair(this, i - 1));
// Solution by Arne Mertz with single ctor argumen
const std::vector<A*> ctor_args1(n, this);
const std::vector<B> bs_vector(ctor_args1.begin(), ctor_args1.end());
// Solution by Arne Mertz using intermediate creator objects
std::vector<std::pair<A*, unsigned>> ctor_args2;
ctor_args2.reserve(n);
for (unsigned i = 0; i != n; ++i)
ctor_args2.push_back(std::make_pair(this, i));
const std::vector<B> bs_vector2(ctor_args2.begin(), ctor_args2.end());
}
Theoretically vector has the properties you need. As you noted, actions that possibly do assignments to the contained type, including especially any sequence modifications (empace_back, push_back, insert etc.) are not supported if the elements are noncopyable and/or nonassignable. So to create a vector of noncopyable elements, you'd have to construct each element during vector construction.
As Steve Jessop points out in his answer, if you define the vector const in the first place you won't even be able to call such modifying actions - and of course the elements remain unchanged as well.
If I understand correctly, you have only a sequence of constructor arguments, not the real object sequence. If it's only one argument and the contained type has a corresponding constructor, things shoule be easy:
struct C
{
const int i_;
C(int i) : i_(i) {}
};
int main()
{
const std::vector<C> theVector { 1, 2, 3, 42 };
}
If the constructor is explicit, you have to make a list first or explicitly construct the objects in the initializer-list:
int main()
{
auto list = { 1, 2, 3, 4 };
const std::vector<C> theVector (std::begin(list), std::end(list));
const std::vector<C> anotherVector { C(1), C(44) };
}
If it's more than just one argument per constructed object, consider a intermediate creator object:
struct C
{
const int i_;
C(int i, int y) : i_(i+y) {}
};
struct CCreator
{
int i; int y;
explicit operator C() { return C(i,y); }
};
int main()
{
const std::vector<CCreator> ctorArgs = { {1,2}, {3,42} };
const std::vector<C> theVector { begin(ctorArgs), end(ctorArgs) };
}
I think const std::vector<T> has the properties you ask for. Its elements aren't actually defined with const, but it provides a const view of them. You can't change the size. You can't call any of the member functions that need T to be movable, so for normal use they won't be instantiated (they would be if you did an extern class declaration, so you can't do that).
If I'm wrong, and you do have trouble because T isn't movable, try a const std::deque<T> instead.
The difficulty is constructing the blighter -- in C++11 you can do this with an initializer list, or in C++03 you can construct a const vector from a non-const vector or from anything else you can get iterators for. This doesn't necessarily mean T needs to be copyable, but there does need to be a type from which it can be constructed (perhaps one you invent for the purpose) .
Add a level of indirection by using a std::shared_ptr. The shared pointer can be copied and assigned as usual, but without modifying the object that is pointed to. This way you should not have any problems, as the following example shows:
class a
{
public:
a(int b) : b(b) { }
// delete assignment operator
a& operator=(a const&) = delete;
private:
// const member
const int b;
};
// main
std::vector<std::shared_ptr<a>> container;
container.reserve(10);
container.push_back(std::make_shared<a>(0));
container.push_back(std::make_shared<a>(1));
container.push_back(std::make_shared<a>(2));
container.push_back(std::make_shared<a>(3));
Another advantage is the function std::make_shared which allows you to create your objects with an arbitrary number of arguments.
Edit:
As remarked by MvG, one can also use std::unique_ptr. Using boost::indirect_iterator the indirection can be removed by copying the elements into a new vector:
void A::foo(unsigned n)
{
std::vector<std::unique_ptr<B>> bs_vector;
bs_vector.reserve(n);
for (unsigned i = 0; i != n; ++i)
{
bs_vector.push_back(std::unique_ptr<B>(new B(this, i)));
}
typedef boost::indirect_iterator<std::vector<std::unique_ptr<B>>::iterator> it;
// needs copy ctor for B
const std::vector<B> bs_vector2(it(bs_vector.begin()), it(bs_vector.end()));
// work with bs_vector2
}
I also encounter this problem, the use case in my code is to provide a thread-safe vector, the elements number is fixed and are atomic numbers. I have read all the great answers here. I think we may also consider my solution:
Just inherited the std::vector and hide the modifiers such as push_back, emplace_back, erase, then we get a fixed size vector. We can only access and modify the elements with operator [].
template <typename T>
class FixedVector : protected std::vector<T> {
public:
using BaseType = std::vector<T>;
FixedVector(size_t n) : BaseType(n) {}
FixedVector(const T &val, size_t n) : BaseType(val, n) {}
typename BaseType::reference operator[](size_t n) {
return BaseType::operator[](n);
}
};
I've read about solution const A a[3] = { {0,0}, {1,1}, {2,2} }, but in my program const can't be used:
class Paper: public PaperQueue{
...
protected:
typedef int (Utils::*funcPtr) (int, int); //I use external function there
funcPtr p;
Utils* fptr;
public:
int pricefunc(){
addprice = (fptr->*p) (t,price);
}
Paper(int n, unsigned int pr):PaperQueue(n){
...
p=&Utils::commonpricefunc;
}
void Put(int a){
...
}
...
}
class Bank{
...
void Buy(Paper &p){
(/*this function modifies many parameters in 'p'*/)
...
}
...
}
int main(){
Bank B;
int pn=5;
/* ? */ const Paper p[pn] = {{5,15},{5,15},{5,15},{5,15},{5,15}}; /* ? */
int paperloop=0;
...
p[paperloop].Put(p[paperloop].addprice);
B.Buy(p[paperloop]);
...
That gives me a LOT of errors(with pricefunc(),Put(),Buy(),...), or just "variable-sized object āpā may not be initialized". Is there any way to make this array work? (Everything works fine if not to pass any parameters to constructor!)
You can't use initializer lists for classes (non-PODs) because that would bypass the call to the constructor. You'll have to change it to a POD or use std::vector in the following ways:
If the class is copyable, as it appears to be, you can create a std::vector and fill it with the values you want:
const vector<Paper> papers(5, Paper(5, 15));
If you want to initialize it with different values, you can use an initializer list, but this is only supported in C++11:
const vector<Paper> papers = {Paper(1, 1), Paper(2, 2)};
Without C++11, you'll have to add the elements one by one, but then you can't make the vector const:
vector<Paper> papers;
papers.push_back(Paper(1, 1));
papers.push_back(Paper(2, 2));
Please check the code below, it can be compiled:
class Paper {
public:
int x, y;
};
int main() {
Paper p[5] = {{5,15}, {5,15}, {5,15}, {5,15}, {5,15}};
}
Please refer this post for more details, I think it explains very well