I have a design which includes 3 classes as my data structures. Let's call the classes A, B, and C.
I have to instantiate objects of A, B, and C while parsing my input. Each object of class C needs to keep track of the corresponding objects in classes A and B. My current implementation looks like this:
class C {
private:
A* a;
B* b;
public:
void setA(A* a);
void setB(B* b);
}
I assign a and b when I create the objects of A and B using new operator. The problem is that I do not want an object of class C to be able to modify a and b. In fact, I only need to know which a and b correspond to a specific c.
One solution could be to define a and b as const pointers/object references. However, in the case of object references, I need to define them as soon as I declare them. The problem is that I am parsing several files and I cannot assign the proper references to a and b when I define them. In other words, a and b are created at different times in my program and may not be available when I create c.
Recently, I read that it's better to avoid raw pointers as much as possible and that's why I'm trying to implement this using object references instead of pointers. Actually, this is giving me a hard time to figure out which one to use at different stages of my program.
My questions are as follows:
1) Is it better to use object references instead of pointers in this specific question?
2) While this approach works for pointers, what should I do to assign constant references to a and b if I prefer to use object references instead of pointers?
3) If I use unique_ptr for a and b, what would be the solution to this problem?
It is good modern C++ style to avoid using raw pointers. See
Chapter 4 of Effective Modern C++ by Scott Meyers for details.
However, this doesn't mean you cannot use pointers. I'd also recommend the reading Effective C++, More Effective C++, and Effective STL.
So nomenclature wise, the reference or pointer are both pointing
to the same object. Under the covers, you are copying around memory
addresses of the object in question.
Now to use a const pointer (or reference) the object itself doesn't
have to be const. If the function takes a const type* or const
type&, the type system will tack on the const for you.
What I think you want is a const pointer. Here the item being
pointed to is const, and not the memory address, so you do not have
to initialize the parameters on construction. Issue with the const
reference is what would you initialize it as? The const type* can
be set to nullptr on construction, but a reference doesn't have a
way to have a null value. I'd say this is important here because
you will want to be able t tell if the caller assigned a value to a
or b. If they didn't, and you properly initialized the member
variables to nullptr, you can test against that to know they weren't
set.
So in this case, the actual memory to be owned by a
std::unique_ptr<> and you would pass down a reference or pointer to
the object. In your situation, sending down the address/pointer is
the only reasonable thing to do. you'll want to initialize the
value to nullptr on construction. Then you'll be able to tell if
the caller assigned a value, because the pointer is not null. If
you wanted to use a const type&, you'd have to set a valid value at
construction time, and since their is no null&, their is no obvious
way to do it.
Also, though this wasn't part of your question, I would document who really owns the memory. One thing I like about using std::unique_ptr<> is that is makes ownership obvious.
Your updated example:
class C {
private:
const A* a;
const B* b;
public:
void setA(const A* a);
void setB(const B* b);
}
The problem is that I do not want an object of class C to be able to modify a and b. In fact, I only need to know which a and b correspond to a specific c.
Use a const pointer:
A const* a;
A const* b;
Then deference them, and they will be objects.
Use pointers instead of references, as if you have an instance of C in either class A or B, you will get an error. Using pointers avoids that
(1)It does not matter; you should use pointers because it is easier to see when you are passing a reference. For example:
function(a); // Not sure if it is a reference
function(&a); // You know it is that actual object
(2) Deference the const pointer, and it will make it a const "reference"
Related
Could you please clear up a question for me regarding pointer vs object in C++. I have the below code that has a class called "person" and a list that allows for 100 objects of that class type.
class person {...}
int main {
person* mylist;
mylist = new person[100];
mylist[0].set_name("John")
// ...
}
In this code I can call a method of the class by mylist[0].set_name() meaning (by my understanding) that mylist[0] is an object (hence the . operator to call a method). The code works fine.
I have another project where the "person" class is used as a base class to derive classes "carpenter" and "welder". The derived classes simply overwrite a virtual function called salary in the base "person" class to allow for a different calculation of salary.
person* mylist[100];
mylist[0] = new carpenter;
mylist[0]->set_name("John");
This code works fine as well. My question is - why in the first code I can call the set_name method using the . (meaning mylist[0] is an object) and in the second code I have to use the -> operator (meaning mylist[0] is a pointer to the object)?
T* represents a pointer type, which represents a variable that contains a "reference" (usually a memory address) to some instance of type T. Using a real world comparison, a T* pointer stands to T like a street address stands to a building.
Pointers allow you to refer to some instance owned by some other variable, and you can use a valid, non null instance of T* to read and write on a T. In this, they are similar to another C++ concept, references (written as T&), which allow you to alias variables, but differ significantly from pointers by not being objects in their own regard.
A pointer is, in fact, an object itself, with each pointer variable having its own unique address and being thus storable and referenceable. For instance, you can have pointers to pointers (T**) and references to pointers (T*&), but not pointers to references - pointers exist, while references may not (they are usually implemented as pointers underneath though).
To reflect the this "indirect" nature of pointers, C and C++ provide you with two different operators which allow you to dereference a pointer (* and ->), and to reference a variable (&).
For instance, you may do the following:
struct A { int x; };
// ...
A a {};
A *aptr { &a }; // `&` takes the address of `a` and stores it into the `aptr` variable of type `A*`
aptr->x = 33; // `->` is equivalent here to `(*aptr).x`, a.x is now 33
A a2 {};
A **aptrptr { &aptr }; // pointer to pointer
*aptrptr = &a2; // `aptr` now points to `a2`
operator-> is basically syntactic sugar that avoids you some cumbersome expressions like (*aptr).x.
References, being basically just aliases to something else, do not need any special syntax at all, and are always converted transparently when neeeded:
int x { 33 };
int &xref { x }; // `xref` refers to `x`
xref = 12; // `x` is now 33
int y = xref; // copies `x` into `y`, no special syntax needed
Pointers are also used in the C language to access arrays, which always decay to a pointer as soon as they are referred to in expressions. This is messy and it's one of the reasons std::vector and std::array should always be used in their place when feasible.
int x[33];
x[3] = 44; // equivalent to `*(&x[0] + 3) = 44`
Finally, the "indirect" nature of pointers and references allow C++ to convert a Derived* to a Base*, given that a derived class contains a full instance of its base (it gets more complicated with multiple inheritance though).
Every class that inherits or contains from another class containing virtual methods will include a hidden pointer to a _Virtual Method Table`, a list of pointers to functions which will be used to dispatch the virtual methods to the correct implementation.
PS: in modern C++, you should rarely need raw pointers. The correct approach is to use containers such as std::vector, std::array and std::string, and special pointer-like wrappers called smart pointers (like std::unique_ptr) every time you need a pointer for some reason. These will handle the lifetime of a pointer for you, avoiding memory leaks and vastly simplifying memory handling. For the same reason, the new operator should be mostly considered as being deprecated and should not be used at all (unless in placement new expressions, are potentially dangerous if used improperly).
basically the first case works like this: you have an array of objects. To access the object fields and methods you use . operator.
In the second case you have an array of pointers to an object. Pointer is just a memory address, that points to an object of some type. In your case, this is an array of pointers to class person. By default, these pointers are invalid; you have to set them to the address of some existing object. new creates an object on the heap, and returns you an address of that object. In order to access the value behind the pointer, you have to de-reference it. The syntax is this:
some_type obj;
some_type* ptr = &obj; // get the address of the object
(*ptr).some_method(); // de-reference the pointer and call it
ptr->some_method(); // same
I have a C++ class that contains objects that have reference members pointing to other objects within the class. This seemed like a good idea at the time, but now I need to implement a deep copy of the whole thing, and I can't see a way to do that that doesn't feel like a clunky hack.
A simplified version of my code looks like this. The question is about writing a copy constructor for A.
class C {
int x, y, z; // nothing complicated stored in this class
public:
// constructor and other methods
};
class B {
C &c1;
C &c2;
public:
// constructor and other methods
};
class A {
C *c_array;
B *b_array; // for each item in this array,
// its 'c1' and 'c2' fields point to members of c_array.
public:
// constructor and other methods
};
A few people have asked how this structure is initialised, so please let me stress that this is irrelevant for answering the question. The initialisation will always satisfy the requirement that the reference members of the items in b_array point to items in c_array, but beyond that the data could be anything. It is important that the copy constructor work for any data that satisfies this property. This is not a problem that can be solved by reusing the existing initialisation code.
The problem is that if I just copy the objects in b_array, their reference members will point to the C objects in the old instance of A. I need to make them point to the corresponding items in the new instance. The only way I can think to do that is this:
for each element of b_array, get the address that its reference member points to, and store that in a pointer
work out the index into the array that that pointer corresponds to using pointer arithmetic
use this index to initialise the reference member of the corresponding element of the new b_array.
My question is, is there a cleaner / simpler / more elegant way? If there isn't, I will just refactor my design to use array indices instead of references throughout.
Perhaps I shouldn't have used reference members - I know some people say it's always better to use pointers. If I had used pointers instead of references, would there be a better solution to this problem? (I can't see one but I don't know.)
A deep copy using references will have to first copy the values (c_array) and then store references to those new values. I cannot see a way of achieving this other than the algorithm you describe.
Using pointers instead of references will not change this. There are various comparisons of pointers vs references. Pointers are less tricky to initialise (create as null and assign when you are ready) and more dangerous to use (might still be null). But you will still have to copy the objects, then find + copy the links to them.
I cannot see a simpler / more elegant way than using array indices. With array indices you will just copy the arrays value by value, and the structure of which index points to which object will be taken care of for you.
You can provide an assignment operator (and a copy ctor) for A that deals with the change of both c_array and b_array in tandem, assuming that B can handle the assignment of C as just a reference/pointer update.
It can be along the lines of:
struct B { ... B& operator=(const C& c) { this->c = &c; return *this; } };
struct A { ...
A& operator=(const A& a) {
c_array = a.c_array;
b_array = a.b_array;
// re-assign pointers/references only using B's `operator=(const C&)` :
std::copy_n(c_array.begin(), c_array.size(), b_array.begin());
return *this;
}
};
A bit messy, but: see live example
Note that if you comment out the std::copy_n line, you can of course observe in the output that the copy isn't detached, that is, the b_array of the copy points to the original's c_array instead of its own.
Presumably not. Here is my use case:
I have two classes A & B.
class A
{
B *b_;
};
class B
{
public:
B(): b_string_("") {};
private:
std::string b_string_;
};
I want b_ to always point to a B object. I want b_ to point to an "empty" B object instead of nullptr so that I can always dereference *b_ in a defined manner to get an empty b_->b_string. So I thought I would create a global "null B object": const B null_b. But I can't (naturally) use this A ctor:
A(): b_(&null_b) {};
since b_ cannot point to a const variable. If not a "null B object", b_ needs to point to mutable B objects.
Making the global non-const solves the problem but I want the protection of const so I can guarantee the "null object" never changes.
FWIW, this involves a large project where b_ is pointing to an vector of B objects in another class. I could add an empty B object to that vector but that strikes me as kludgy.
Is there a method or pattern to solve my problem?
Instead of holding a pointer to a B object, create a base class with virtual methods and store pointers to that. Derive both your B class and a Null_B class from it, but don't let methods on Null_B do modifications. Now even though your Null_B object won't be const, it doesn't matter anymore.
As an extra layer of protection you could make any attempt to modify the null_b object throw an exception so that you can detect and find your logic error.
You can't have a "non-const" pointer point at a const object. And unfortunately, using const_cast to remove the const-ness of the object will mean that some code later can try to modify the object. (Note that it's undefined behaviour to cast away const unless the original object is non-const, so technically, the compiler is allowed to generated code that crash if this happens. Unfortunately, many cases, it WON'T crash when the object is something more complex than const char * or const int [] - allowing the code to happly continue after overwriting your object that you didn't want to be written).
However, since the B class has a b_string_ member that is private, no outside object could touch it, so you could ensure that any usage of b_string_ is done through a virtual function (or multiple virtual functions), then derive another class from B where the, and the virtual function(s) says "Sorry, you can't do that" when the code tries to modify b_string in the derived object.
Well, maybe it's totally off the point, but... Could you use instance of B instead of pointer to B inside A? This would solve potential nullptr dereferencing.
EDIT well, if B is too big, then you can create a lightweight wrapper around it, and store instance of that wrapper inside A. The wrapper would provide you something meaningful if B is nullptr.
I've been programming C++ for a while now and I'm starting to doubt that the rule use references whenever possible should be applied everywhere.
Unlike this related SO post I'm interested in a different kind of thing.
In my experience the reference/pointer mix messes up your code:
std::vector<Foo *> &x = get_from_somewhere(); // OK? reference as return value
some_func_pass_by_ref(x); // OK reference argument and reference variable
some_func_by_pointer(x[4]); // OK pointer arg, pointer value
some_func_pass_elem_by_ref(*x[5]); // BAD: pointer value, reference argument
some_func_that_requires_vec_ptr(&x); // BAD: reference value, pointer argument
One option would be to replace & with * const like Foo & with Foo * const
void some_func_by_ref(const std::vector<Foo * const> * const); // BAD: verbose!
this way at least the traversals are gone. and me rewriting function headers is gone, because all arguments will be pointers... at the price of polluting the code with const instead of pointer arithmetic (mainly & and *).
I would like to know how and when you apply use references whenever possible rule.
considering:
minimal rewriting of function prototypes (i.e.: oh damn I need need to rewrite alot of prototypes because I want to put this referenced element into a container)
increasing readability
avoid application of * to transform Foo* to Foo& and vice versa
avoid excessive const usage as in * const
NOTES: one thing I figured is to use pointers whenever I intend to ever put the element into an STL container (see boost::ref)
I don't think this is something C++03 specific but C++11 solutions are fine if they can be backported to C++03 (i.e.: NRVO instead of move-semantics).
When should I use references in C++?
When you need to treat a variable like the object itself (most cases when you don't explicitly need pointers and don't want to take ownership of an object).
I would like to know how and when you apply use references whenever possible rule.
whenever possible, except when you need to:
work on the address (log the address, diagnose or write custom memory allocation, etc)
take ownership of parameter (pass by value)
respect an interface that requires a pointer (C interoperability code and legacy code).
Bjarne Stroustrup stated in his book that he introduced references to the language because operators needed to be called without making a copy of the object (that would mean "by pointer") and he needed to respect syntax similar to calling by value (that would mean "not by pointer") (and thus references were born).
In short, you should use pointers as little as possible:
if the value is optional ("can be null") then use a std::optional around it, not a pointer
if you need to take ownership of the value, receive parameter by value (not a pointer)
if you need to read a value without modifying it, receive parameter by const &
if you need to allocate dynamically or return newly/dynamically allocated object, transmit value by one of: std::shared_ptr, std::unique_ptr, your_raii_pointer_class_here - not by (raw) pointer
if you need to pass a pointer to C code, you should still use the std::xxx_ptr classes, and get the pointer using .get() for getting the raw pointer.
one thing I figured is to use pointers whenever I intend to ever put the element into an STL container (or can I get rid of this?)
You can use Boost Pointer Container library.
IMHO the rule stands because raw pointers are dangerous because ownership and destruction responsibility becomes rapidly unclear. Hence the multiple encapsulations around the concept (smart_ptr, auto_ptr, unique_ptr, ...).
First, consider using such encapsulations instead of raw pointer in your container.
Second, why do you need to put pointers in a container ? I mean, they're meant to contain full objects ; they have an allocator as template argument for precise memory allocation after all. Most of the time, you want pointers because you have an OO-approach making heavy use of polymorphism. You should reconsider this approach. For example you can replace:
struct Animal {virtual std::string operator()() = 0;};
struct Dog : Animal {std::string operator()() {return "woof";}};
struct Cat : Animal {std::string operator()() {return "miaow";}};
// can not have a vector<Animal>
By something like this, using Boost.Variant :
struct Dog {std::string operator()() {return "woof";}};
struct Cat {std::string operator()() {return "miaow";}};
typedef boost::variant<Dog, Cat> Animal;
// can have a vector<Animal>
This way when you add a new animal, you inherit nothing, you just add it to the variant.
You can also consider, a little bit more complicated, but far more generic, using Boost.Fusion :
struct Dog {std::string talk; Dog() : talk("wook"){}};
struct Cat {std::string talk; Cat() : talk("miaow"){}};
BOOST_FUSION_ADAPT_STRUCT(Dog, (std::string, talk))
BOOST_FUSION_ADAPT_STRUCT(Cat, (std::string, talk))
typedef boost::fusion::vector<std::string> Animal;
int main()
{
vector<Animal> animals;
animals.push_back(Dog());
animals.push_back(Cat());
using boost::fusion::at;
using boost::mpl::int_;
for(auto a : animals)
{
cout << at<int_<0>>(a) << endl;
}
}
This way you do not even modify an aggregate like variant nor the algorithms on animals, you just need to provide a FUSION_ADAPT matching the used algorithms prerequisites. Both versions (variant and fusion) let you define orthogonal object groups, a useful thing you can not do with inheritance trees.
The following ways seem reasonable dealing with this:
boost and C++11 have a class that can cheaply be used to store references in a container: Reference Wrapper
A good advice is to use the handle/body idiom more often instead of passing around raw pointers. This also solves the ownership issue of the memory that is governed by the reference or the pointer. Sean Parent from Adobe has pointed this out at a talk at going native 2013.
I chose to use the Handle/Body Idiom approach because it gives pointers automatically copy/assign behaviour while hiding the underlying implementation and ownership semantics. It also acts as kind of a compile time firewall reducing header file inclusion.
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.