Make variable unchangeable without copying in C++ - c++

I'm working on some code in which a variable of type std::vector<double> is declared, before the value is specified. I can't define the value together with declaration, because it takes many lines of code to set the value. The thing is that this variable is a constant in essence, meaning it shouldn't be modified once it's set. However, it can't be declared const.
One way is to create another variable which is const and copy the value into it. const std::vector<double> a(b); would do, and use a instead of b in the program. However, my variable can be large and I wish to learn a way other than having to perform copying.
Any suggestions from you guys?

You may create a function to initialize it. In worst, you have a move. at best you have (N)RVO (return value optimization).
std::vector<Object> CreateBigVector();
And then
const std::vector<Object> myObject = CreateBigVector();

One way is to create a function
std::vector<Object> CreateYourVector();
and use it to initialise
const std::vector<Object> vec = CreateYourVector();
Another (technically a variation) is to create a helper class that contains your vector, and do all the work in a constructor
class Helper
{
std::vector<Object> vec;
public:
Helper()
{
// initialise your vector here
};
const std::vector<Object> &TheVec() const {return vec;};
};
const Helper helper;
The above techniques can be combined, for example change the constructor
Helper() : vec(CreateYourVector()) {};
These techniques can also be mixed with others, such as the singleton pattern.

I think the problem is about scoping. You have to separate your problem into two different scopes:
a scope where you build up your vector
a (or others) scope(s) where you use it
In the scope where you build up your vector, it logically isn't a const variable. Once you have built it, you want it not to be changed anymore. So you may want to refer to it through a const &.
I'd go this way:
define a function std::vector<double> build_up()
inside build_up, you define a non-const vector and you can build it
when you're done, you can return it by value (RVO will avoid any copy)
refer to the object returned by build_up() as a const object
I.e.
const std::vector<double> v = build_up();

In c++11, you can use the initial list to define a const vector. I think it is a easiest way. Try it: const vector<double> = {1.0, 2.0, 3.0};. It will not take many lines of code to set the value. I hope this can help you.

The traditional approach would be to only expose a handle that enforces constness and avoids making expensive copies outside the context where the vector is created and initialized. Such handle would be a const pointer or reference.
Since you are using std::vector you can benefit from modern c++ facilities, since std::vector supports features like move semantics off-the-shelf.
In particular, I suggest you to budget some time to have a look at:
move semantics
smart pointers
which upgrade the traditional way of passing around raw pointers. They enforce ownership semantics (which context owns the object) and allow you to express your intentions in a very precise way through the code.

Related

Can you initialise "static const vectors" of unique_ptrs? (C++17 with GCC 7.3)

I'm trying to create a static const list of default objects (Rules) that are to big to be frequently copied and as such I want to store them in a vector of unique_ptr<>. I've noticed that similar questions has made the rounds a few times but I'm unclear as to whether this is actually doable (I'm leaning towards not doable). I.e.
You can't use initializer_list with unique_ptr since access to the members are const resulting in a copy operation.
You can't pass temporaries in by reference resulting in a copy operation.
Thus both:
static const std::vector<std::unique_ptr<std::string>> kStrings = {
std::unique_ptr<std::string>(new std::string("String 1")),
std::unique_ptr<std::string>(new std::string("String 1"))
};
and
static const std::vector<std::unique_ptr<std::string>> kStrings(
std::unique_ptr<std::string>(new std::string("String 1")),
std::unique_ptr<std::string>(new std::string("String 1"))
);
are not feasible.
Am I misunderstanding? Is there another way to initialize such a vector or is this a case of rethinking the design? The simplest alternative I can think of is to create the objects a static const and then referencing those as raw pointers. For example:
static const std::string kString1 = "String 1";
static const std::string kString2 = "String 2";
static const std::vector<const std::string*> kStrings = {&kString1, &kString2};
It feels nasty, but the code interfaces remains relatively unchanged and since it does not leave the scope of the class it is also transparent to the users.
Any thoughts, corrections or better alternatives is appreciated.
EDIT - Regarding this question, I've tested the solution and it also works. My problem with the solution is it enables initializer_list to used in a way they were not designed to be used and I don't know what unintended consequence that will have, if any.
Am I misunderstanding? Is there another way to initialize such a vector
There is, call a function that returns a non-const vector to use as an initializer. It doesn't even have to be named. It could be an immediately invoked lambda.
static const std::vector<std::unique_ptr<std::string>> kStrings = [] {
std::vector<std::unique_ptr<std::string>> ret;
// populate ret
return ret;
}(); // <-- Invoke the lambda immediately after defining it.
Now you can have your complex initialization logic and treat kStrings as const still. Furthermore, it's quite likely compilers will inline the lambda entirely, so there isn't even going to be the overhead of a function call. It really is having your cake and eating it too.
Though one has to wonder why you'd use a vector of unique pointers to strings (a value type). A vector already owns its content. So you could possibly cut the middleman, and that will simplify initialization as well.

What happens when using pass by reference and member initialization lists in C++ classes?

Okay, so I have a large vector say
vector<vector<vector<int>>>
of 10000 by 10000 by 10000.
I have a class which has such a vector as a private member variable:
class foo {
private:
vector<vector<vector<int>>> myvector
};
I have a constructor for my class that uses pass by reference and initializer list:
foo(vector<vector<vector<int>>> &myvector_in) : myvector(myvector_in);
I want to know what's exactly happening in terms of memory usage. Is the private myvector the same as the one that was originally declared, or is it a copy.
Basically, I want to know if there are ever two version of myvector in memory.
Thank You!
Here is a fishing tip.
Fairly easy to answer yourself. Set [0][0][0] of myvector_in to a known value. Invoke the constructor and inside it also set [0][0][0] but of myvector to a different value. Once the constructor has returned, print the content of myvector_in. If it's the same as the one you original set you must conclude that the two vectors are different entities, thus one was copied into a different one. If they are the same than you can conclude they are in fact the same instances.
You could also print addresses to get a better sense of what's what.
I must point out, the memory requirement mention in your original question are in the realm of super computer, you got one?
You have a member of type vector<vector<vector<int>>> and initialize it with another vector<vector<vector<int>>>. How would it be possible not to have said data twice in memory? Thats more a matter of logic than a matter of c++.
Alternatives
You could store a pointer vector<vector<vector<int>>>* or a reference vector<vector<vector<int>>>& to the vector in an appropriate class member. Or use one of the smart pointers to do so. In any of these cases some serious thinking about memory management is a good idea.
Or you use a move constructor, which is moving the passed in vector in your member vector.
using vec = std::vector<std::vector<std::vector<int>>>;
class foo {
public:
foo() = delete;
foo(const vec&) = delete;
foo(vec&& myvector_in) : myvector(std::move(myvector_in)) {};
private:
vec myvector;
};
Of course that will render that argument passed to the constructor useless but that a trivial consequence of the not-copying you want.
You can pass your vector to that constructor if you first cast it to an rvalue using std::move:
foo my_foo(std::move(test));
The easy way of addressing this issue in C++11 (and newer) is to accept the constructor argument by value:
struct foo {
using vec=std::vector<std::vector<std::vector<int>>>; // from DrSvanHay
foo(vec v) : myvector(std::move(v)) {}
private:
vec myvector;
};
Surprisingly, this actually minimizes copies:
If the client has a vector cv;, cv gets copied into the parameter v, but that copy was necessary to have cv and foo::myvector upon completion.
If the client passes std::move(cv), cv gets moved into v and there is no copy.
If the client passes make_vector(...), the parameter v is move-initialized from the return value (or, in C++17, is the return value).
(In all these cases, v is then moved into foo::myvector, of course.)

C++ returning an object copy

I wrote the following code:
class MyObjectHolder {
public:
std::vector<int> getMyObject() const {
return myObject;
}
private:
std::vector<int> myObject;
};
At some point of my program I attempt to use the getMyObject method and use only const methods on the retrieved object:
const std::vector<int> myObject = myObjectHolder.getMyObject();
myObject.size();
int a = myObject.front();
Now, is it possible that the compiler will optimize this code so that no copies of the std::vector<int> are done?
Is it somehow possible that the compiler determines that I'm only using the const methods on the retrieved object (and let's assume there is no mutable nonsense happening behind it) and it would not make any copies of the objects and perform these const operations on the private member of the MyObjectHolder instead?
If yes, would it be possible if I didn't explicitly declare the const std::vector<int> myObject as const?
If no, what are the reasons not to do this? In which cases this optimization would be to hard to implement / deduce that it's possible and correct here / etc... ?
Now, is it possible that the compiler will optimize this code so that no copies of the std::vector<int> are done?
No, the compiler doesn't know what callers will do with that object unless you are making use of global optimization over all code that uses the object (the compiler can't generally make assumptions about its use; moreover if object is exported from a dll it can't make any assumption at all).
If yes, would it be possible if I didn't explicitly declare the const std::vector myObject as const?
No, anyway the conversion from non-const to const could be implicit.
If no, what are the reasons not to do this? In which cases this optimization would be to hard to implement / deduce that it's possible and correct here / etc... ?
It's an optmiziation that should be done inside getMyObject() but the compiler can't be sure that callers won't cast away the const. Actually this is a very old debate about the use of const, usually I think it's more clear to always think about const as something for programmers and not for compilers.
I would suggest to use
const std::vector<int>& getMyObject() const {
return myObject;
}
It would return the constant reference of myObject without copy that.
And use the result with
const std::vector<int>& myObject = myObjectHolder.getMyObject();
It is possible Copy Elision and Return Value Optimization will kick in. If you use C++ compiler with C++11 support, then you may get it optimised by move semantics.
I'd recommend to read the excellent article Want Speed? Pass by Value by Dave Abrahams with discussion in the comments below it.
However, for details you should refer documentation of your C++ compiler.

RAII: Initializing data member in const method

In RAII, resources are not initialized until they are accessed. However, many access methods are declared constant. I need to call a mutable (non-const) function to initialize a data member.
Example: Loading from a data base
struct MyClass
{
int get_value(void) const;
private:
void load_from_database(void); // Loads the data member from database.
int m_value;
};
int
MyClass ::
get_value(void) const
{
static bool value_initialized(false);
if (!value_initialized)
{
// The compiler complains about this call because
// the method is non-const and called from a const
// method.
load_from_database();
}
return m_value;
}
My primitive solution is to declare the data member as mutable. I would rather not do this, because it suggests that other methods can change the member.
How would I cast the load_from_database() statement to get rid of the compiler errors?
This is not RAII. In RAII you would initialize it in the constructor, which would solve your problems.
So, what you are using here is Lazy. Be it lazy initialization or lazy computation.
If you don't use mutable, you are in for a world of hurt.
Of course you could use a const_cast, but what if someone does:
static const MyClass Examplar;
And the compiler decides it is a good candidate for Read-Only memory ? Well, in this case the effects of the const_cast are undefined. At best, nothing happens.
If you still wish to pursue the const_cast route, do it as R Samuel Klatchko do.
If you thought over and think there is likely a better alternative, you can decide to wrap your variable. If it was in class of its own, with only 3 methods: get, set and load_from_database, then you would not worry about it being mutable.
You are basically implementing a caching mechanism. Personally I think it's OK to mark cached data as mutable.
As Matthieu already pointed out, what you're trying to do here has little (if anything) to do with RAII. Likewise, I doubt that any combination of const and mutable is really going to help. const and mutable modify the type, and apply equally to all access to an object of that type.
What you seem to want is for a small amount of code to have write access, and anything else only read access to the value. Given the basic design of C++ (and most similar languages), the right way to do that is to move the variable into a class of its own, with the small amount of code that needs write access as part of (or possibly a friend of) that class. The rest of the world is given its read-only access via the class' interface (i.e., a member function that retrieves the value).
The (presumably stripped down) MyClass you've posted is pretty close to right -- you just need to use that by itself, instead of as part of a larger class with lots of other members. The main things to change would be 1) the name from MyClass to something like lazy_int, and 2) (at least by my preference) get_value() should probably be renamed to operator int(). Yes, m_value will probably need to be mutable, but this doesn't allow other code to write the value, simply because other code doesn't have access to the value itself at all.
Then you embed an object of that type into your larger class. The code in that outer class can treat it as an int (on a read-only basis) thanks to its operator int(), but can't write it, simply because the class doesn't give any way to do so.
[ LOOK MA! NO CASTS! :)) ]
struct DBValue
{
int get_value();
private:
void load_from_database();
int value;
};
struct MyClass
{
MyClass(): db_value(new DBValue()) {}
~MyClass() { delete db_value; }
int get_value() const;
private:
DBValue * const db_value;
};
int MyClass::get_value() const
{
return db_value->get_value(); // calls void load_from_database() if needed
}
The idea is to have a politically correct MyClass with const methods not mutating anything but calling both const and non-const methods of aggregated objects via const pointers.
Don't use const_cast here, or you're asking for trouble. Using mutable in this case shouldn't be a problem, but if the profiler didn't suggest otherwise then I think users would be less surprised to see an object that is expensive to construct than an accessor method that is expensive to call the first time.
If your method changes the state of the object (e.g. by changing the state of the underlying database), then the method should not be const. In that case you should have a separate, non-const load-method, that has to be called before the const getter can be called.
This method would require neither const_cast not mutable, and would make the potentially expensive operation explicit.

C++ reference type recommended usage

I am programming in C++ more then 5 years, and have never met any place where reference of the variable is recommended to use except as a function argument (if you don't want to copy what you pass as your function argument). So could someone point cases where C++ variable reference is recommended (I mean it gives any advantage) to use.
As a return value of an opaque collection accessor/mutator
The operator[] of std::map returns a reference.
To shorten the text needed to reference a variable
If you miss old-school with Foo do ... statement (that's Pascal syntax), you can write
MyString &name = a->very->long_->accessor->to->member;
if (name.upcase() == "JOHN") {
name += " Smith";
}
another example of this can be found in Mike Dunlavey's answer
To state that something is just a reference
References are also useful in wrapper objects and functors--i.e. in intermediate objects that logically contact no members but only references to them.
Example:
class User_Filter{
std::list<User> const& stop_list;
public: Functor (std::list<User> const& lst)
: stop_list(lst) { }
public: bool operator()(User const& u) const
{ return stop_list.exists(u); }
};
find_if(x.begin(),x.end(),User_Filter(user_list));
The idea here that it's a compile error if you don't initialize a reference in constructor of such an object. The more checks in compile time--the better programs are.
Here's a case where it's handy:
MyClass myArray[N];
for (int i = 0; i < N; i++){
MyClass& a = myArray[i];
// in code here, use a instead of myArray[i], i.e.
a.Member = Value;
}
Use references wherever you want, pointers when you are forced to.
References and pointers share part of their semantics: they are an alias to an element that is not present. The main difference is with memory managements: references express clearly that you are not responsible for the resource. On the other hand, with pointers it is never really clear (unless you mean smart pointers): are you assumed to delete the pointer or will it be deleted externally?
You must use pointers when you must manage memory, want to allow for optional semantics or need to change the element referred to at a later time.
In the rest of cases, where you can use a reference or a pointer, references are clearer and should be preferred.
Now, as you point out, they are really not needed: you can always use pointers for all the reference uses (even parameter passing), but the fact that you can use a single tool for everything does not mean there are no better suited tools for the job.
I tend to use reference members instead of pointers for externally controlled non-optional construction parameters.
EDIT (added example):
Let's say that you have a database and a DAO class having the database as a dependency:
struct Database {};
struct PersonDao {
const Database &m_d;
PersonDao(const Database &d): m_d(d) {}
};
Furthermore, the scope of the database is controlled externally from the DAO:
int main() {
Database d;
PersonDao pd(d);
}
In this case it makes sense to use a reference type, since you don't ever want DAO::m_d to be null, and its lifetime is controlled externally (from the main function in this case).
I use references in function arguments not just to avoid copies but also instead of pointers to avoid having to deal with NULL pointers where appropriate. Pointers model a "maybe there's a value, but maybe not (NULL)", references are a clear statement that a value is required.
... and to make it absolutely clear (-> comments). I tend to avoid pointers to model "maybe there are several values" - a vector is a better option here. Pointers to several values often end up in C-style programming because you usually have to pass the # of elements as well separately.
Use a const reference to give a name to a value, e.g.:
const Vec3 &ba=b-a;
This names the value, but doesn't necessarily create a variable for it. In theory, this gives the compiler more leeway and may allow it to avoid some copy constructor calls.
(Related non-duplicated Stack Overflow question at Const reference to temporary. The Herb Sutter link there has more information about this.)
The argument to the copy-constructor MUST be passed as a reference, since otherwise the copy constructor would need to call it self in an endless recursion (stack overflow).
I tend to agree, but perhaps const return values.
Well you kind of have two choices for aliasing other values(ignoring shared_ptrs and the like): pointers and references.
References must be initialized at construction to refer to something else. So semantically a reference can never be NULL. In reality, though, the underlying data can go away, giving you problems often more difficult to debug than if a pointer went away. So I'm not sure there's a real advantage here unless you were disciplined and consistent with how they were used vis-a-vis referring to items that were dynamically allocated. If you did this with pointers too, you'd avoid the same problems.
Perhaps more importantly, references can be used without thinking about all the issues that arise with pointers. This is probably the main advantage. Semantically a reference is the thing. If you guarantee as the caller/callee that the underlying memory doesn't go away, you don't have to confuse the user with any of the questions that come along with pointers (Do I need to free this? Could this be NULL? etc) and can safely use a reference for convenience.
An example of this might be a function that looks up the corresponding string for an enum,
const std::string& ConvertToString( someEnum val)
{
static std::vector< std::string > lookupTable;
if (lookupTable.empty())
{
// fill in lookup table
}
// ignoring the cast that would need to happen
return lookupTable[val]
}
Here the contract between the caller and the callee guarantees that the return type will always be there. You can safely return a reference, and avoid some of the questions that pointers invite.
References make code prettier. So use them whenever it takes a reference to beautify your code.
i would like to enlist some cases:
1) while writing singleton classes
class singleton
{
singleton();
explicit singleton(const singleton&);
singleton& operator=(const singleton&);
public:
static singleton& instance()
{
static singleton inst;
return inst;
}
};// this is called the 'Meyers' singleton pattern. refer to More Effective C++ by Scott Meyers
it has all the benefits, but avoids using the new operator
**2)**here is no such thing as a null reference. A reference must always refer to some object. As a result, if you have a variable whose purpose is to refer to another object, but it is possible that there might not be an object to refer to, you should make the variable a pointer, because then you can set it to null. On the other hand, if the variable must always refer to an object, i.e., if your design does not allow for the possibility that the variable is null, you should probably make the variable a reference
**3)**Because a reference must refer to an object, C++ requires that references be initialized:
string& rs; // error! References must
// be initialized
string s("xyzzy");
string& rs = s; // okay, rs refers to s
Pointers are subject to no such restriction
The fact that there is no such thing as a null reference implies that it can be more efficient to use references than to use pointers. That's because there's no need to test the validity of a reference before using it
**4)**Another important difference between pointers and references is that pointers may be reassigned to refer to different objects. A reference, however, always refers to the object with which it is initialized: ยค Item M1, P10
string s1("Nancy");
string s2("Clancy");
string& rs = s1; // rs refers to s1
string *ps = &s1; // ps points to s1
rs = s2; // rs still refers to s1,
// but s1's value is now
// "Clancy"
ps = &s2; // ps now points to s2;
// s1 is unchanged
Stream operators are an obvious example
std::ostream & operator<< (std::ostream &, MyClass const &...) {
....
}
mystream << myClassVariable;
You obviously don't want a pointer as checking for NULL makes using an operator very tedious i.s.o. convenient
I've used a reference to an ostream instead of a pointer. I supppose that I prefer references to pointers when the class has a lot of operators.