Does 'auto' type assignments of a pointer in c++11 require '*'?
auto newvar1 = myvector;
// vs:
auto *newvar2 = myvector;
Both of these are the same and will declare a pointer to std::vector<MyClass>
(pointing to random location, since . So basically you can use any one of them. I would prefer myvector
is uninitialized in your example and likely contains garbage)auto var = getVector()
, but you may go for auto* var = getVector()
if you think it stresses the intent (that var
is a pointer) better.
I must say I never dreamt of similar uncertainity using auto
. I thought people would just use auto
and not think about it, which is correct 99 % of the time - the need to decorate auto
with something only comes with references and cv-qualifiers.
However, there is slight difference between the two when modifies slightly:
auto newvar1 = myvector, newvar2 = something;
In this case, newvar2
will be a pointer (and something must be too).
auto *newvar1 = myvector, newvar2 = something;
Here, newvar2
is the pointee type, eg. std::vector<MyClass>
, and the initializer must be adequate.
In general, if the initializer is not a braced initializer list, the compiler processes auto
like this:
It produces an artificial function template declaration with one argument of the exact form of the declarator, with
auto
replaced by the template parameter. So forauto* x = ...
, it usestemplate <class T> void foo(T*);
It tries to resolve the call
foo(initializer)
, and looks what gets deduced forT
. This gets substituted back in place ofauto
.If there are more declarators in a single declarations, this is done for all of them. The deduced
T
must be the same for all of them...
Difference between auto and auto* when storing a pointer
In the snippet you have given there is no difference. The compiler will deduce that p
will be a pointer to C
, either way.
In a more general case, there is a difference;
auto *p = func();
auto p = func();
The first form will cause an error message if func()
returns something that is not a pointer, but the second will not. This is sometimes useful (e.g. in templated code) where there is a need to enforce a requirement that func()
return a pointer rather than (say) an int
. [Although, admittedly, there are more clear and powerful ways to enforce such a requirement, such as traits].
Why should I use a pointer rather than the object itself?
It's very unfortunate that you see dynamic allocation so often. That just shows how many bad C++ programmers there are.
In a sense, you have two questions bundled up into one. The first is when should we use dynamic allocation (using new
)? The second is when should we use pointers?
The important take-home message is that you should always use the appropriate tool for the job. In almost all situations, there is something more appropriate and safer than performing manual dynamic allocation and/or using raw pointers.
Dynamic allocation
In your question, you've demonstrated two ways of creating an object. The main difference is the storage duration of the object. When doing Object myObject;
within a block, the object is created with automatic storage duration, which means it will be destroyed automatically when it goes out of scope. When you do new Object()
, the object has dynamic storage duration, which means it stays alive until you explicitly delete
it. You should only use dynamic storage duration when you need it.
That is, you should always prefer creating objects with automatic storage duration when you can.
The main two situations in which you might require dynamic allocation:
- You need the object to outlive the current scope - that specific object at that specific memory location, not a copy of it. If you're okay with copying/moving the object (most of the time you should be), you should prefer an automatic object.
- You need to allocate a lot of memory, which may easily fill up the stack. It would be nice if we didn't have to concern ourselves with this (most of the time you shouldn't have to), as it's really outside the purview of C++, but unfortunately, we have to deal with the reality of the systems we're developing for.
When you do absolutely require dynamic allocation, you should encapsulate it in a smart pointer or some other type that performs RAII (like the standard containers). Smart pointers provide ownership semantics of dynamically allocated objects. Take a look at std::unique_ptr
and std::shared_ptr
, for example. If you use them appropriately, you can almost entirely avoid performing your own memory management (see the Rule of Zero).
Pointers
However, there are other more general uses for raw pointers beyond dynamic allocation, but most have alternatives that you should prefer. As before, always prefer the alternatives unless you really need pointers.
You need reference semantics. Sometimes you want to pass an object using a pointer (regardless of how it was allocated) because you want the function to which you're passing it to have access that that specific object (not a copy of it). However, in most situations, you should prefer reference types to pointers, because this is specifically what they're designed for. Note this is not necessarily about extending the lifetime of the object beyond the current scope, as in situation 1 above. As before, if you're okay with passing a copy of the object, you don't need reference semantics.
You need polymorphism. You can only call functions polymorphically (that is, according to the dynamic type of an object) through a pointer or reference to the object. If that's the behavior you need, then you need to use pointers or references. Again, references should be preferred.
You want to represent that an object is optional by allowing a
nullptr
to be passed when the object is being omitted. If it's an argument, you should prefer to use default arguments or function overloads. Otherwise, you should preferably use a type that encapsulates this behavior, such asstd::optional
(introduced in C++17 - with earlier C++ standards, useboost::optional
).You want to decouple compilation units to improve compilation time. The useful property of a pointer is that you only require a forward declaration of the pointed-to type (to actually use the object, you'll need a definition). This allows you to decouple parts of your compilation process, which may significantly improve compilation time. See the Pimpl idiom.
You need to interface with a C library or a C-style library. At this point, you're forced to use raw pointers. The best thing you can do is make sure you only let your raw pointers loose at the last possible moment. You can get a raw pointer from a smart pointer, for example, by using its
get
member function. If a library performs some allocation for you which it expects you to deallocate via a handle, you can often wrap the handle up in a smart pointer with a custom deleter that will deallocate the object appropriately.
C++ auto keyword. Why is it magic?
auto
was a keyword that C++ "inherited" from C that had been there nearly forever, but virtually never used because there were only two possible conditions: either it wasn't allowed, or else it was assumed by default.
The use of auto
to mean a deduced type was new with C++11.
At the same time, auto x = initializer
deduces the type of x
from the type of initializer
the same way as template type deduction works for function templates. Consider a function template like this:
template<class T>
int whatever(T t) {
// point A
};
At point A, a type has been assigned to T
based on the value passed for the parameter to whatever
. When you do auto x = initializer;
, the same type deduction is used to determine the type for x
from the type of initializer
that's used to initialize it.
This means that most of the type deduction mechanics a compiler needs to implement auto
were already present and used for templates on any compiler that even sort of attempted to implement C++98/03. As such, adding support for auto
was apparently fairly easy for essentially all the compiler teams--it was added quite quickly, and there seem to have been few bugs related to it either.
When this answer was originally written (in 2011, before the ink was dry on the C++ 11 standard) auto
was already quite portable. Nowadays, it's thoroughly portable among all the mainstream compilers. The only obvious reasons to avoid it would be if you need to write code that's compatible with a C compiler, or you have a specific need to target some niche compiler that you know doesn't support it (e.g., a few people still write code for MS-DOS using compilers from Borland, Watcom, etc., that haven't seen significant upgrades in decades). If you're using a reasonably current version of any of the mainstream compilers, there's no reason to avoid it at all though.
More recent revisions of the standard have added a few new places that auto
can be used. Starting with C++14, you can use auto
for the type of a parameter to a lambda:
[](auto s) { return s + 1; }
This does essentially the same thing as the example above--even though it doesn't explicitly use template
syntax, this is basically a template that deduces the type of the parameter, and instantiates the template over that type.
That was convenient and useful enough that in C++20, the same capability was added for normal functions, not just lambdas.
But, just as before all of this really comes down to using the same basic type deduction mechanism as we've had for function templates since C++98. auto
allows that to be used in more places, and more conveniently, but the underlying heavy lifting remains the same.
Can I use if (pointer) instead of if (pointer != NULL)?
You can; the null pointer is implicitly converted into boolean false while non-null pointers are converted into true. From the C++11 standard, section on Boolean Conversions:
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a
prvalue of type
bool
. A zero value, null pointer value, or null member pointer value is converted to
false
;
any other value is converted to
true
. A prvalue of type
std::nullptr_t
can be converted to a prvalue of
type
bool
; the resulting value is
false
.
Pointer to member variable - auto type in C++
auto
is not the solution you're looking for. Types in C++ cannot change at runtime. auto
must always be inferred from it's initializer. In your case, there is no initializer so it won't work.
What I suggest to you would be to move the auto
into the parameter of a lambda:
void member(string member_string)
{
// Here, the type of `ptr` will be
// inferred when the lambda is called
// ~~~~v~~~~
auto do_magic = [](auto ptr) {
// loop over objects and do some magic with them
};
if(member_string == "time") do_magic(&DETECTOR::time);
if(member_string == "energy") do_magic(&DETECTOR::energy);
if(member_string == "number") do_magic(&DETECTOR::number);
}
The lambda is the equivalent of a function template:
template<typename T>
void do_magic(T ptr) {
// loop over objects and do some magic with them
}
[ERROR ]request for member in which is of pointer type maybe you meant to use - ?) in C BST
A is a ABR**
, so a struct noud***
, so (*A)
is a struct noud**
not a struct noud*
and (*A)->caracterise
is wrong (but (**A)->caracterise
legal)
What does ** do in C language?
In C arguments are passed by values. For example if you have an integer varaible in main
int main( void )
{
int x = 10;
//...
and the following function
void f( int x )
{
x = 20;
printf( "x = %d\n", x );
}
then if you call the function in main like this
f( x );
then the parameter gets the value of variable x
in main. However the parameter itself occupies a different extent in memory than the argument. So any changes of the parameter in the function do not influence to the original variable in main because these changes occur in different memory extent.
So how to change the varible in main in the function?
You need to pass a reference to the variable using pointers.
In this case the function declaration will look like
void f( int *px );
and the function definition will be
void f( int *px )
{
*px = 20;
printf( "*px = %d\n", *px );
}
In this case it is the memory extent occupied by the original variable x
is changed because within the function we get access to this extent using the pointer
*px = 20;
Naturally the function must be called in main like
f( &x );
Take into account that the parameter itself that is the pointer px
is as usual a local variable of the function. That is the function creates this variable and initializes it with the address of variable x
.
Now let's assume that in main you declared a pointer for example the following way
int main( void )
{
int *px = malloc( sizeof( int ) );
//..
And the function defined like
void f( int *px )
{
px = malloc( sizeof( int ) );
printf( "px = %p\n", px );
}
As parameter px
is a local variable assigning to it any value does not influence to the original pointer. The function changes a different extent of memory than the extent occupied by the original pointer px
in main.
How to change the original pointer in the function?
Just pass it by reference!
For example
f( &px );
//...
void f( int **px )
{
*px = malloc( sizeof( int ) );
printf( "*px = %p\n", *px );
}
In this case the value stored in the original pointer will be changed within the function because the function using dereferencing access the same memory extent where the original pointer was defined.
Is auto* useful at compile time or is the auto keyword enough?
None of this “newfangled C++11” has anything to do with efficient compilation, except in very odd corner cases. It’s all there to make it easier for humans to write and comprehend the code. auto*
makes it obvious that you have a pointer-typed value, and the compiler only uses it as an additional typecheck criterion, and will issue a diagnostic if the type is not a pointer type – your code is then malformed and it’s a hard error.
I don’t recall offhand if auto*
can ever participate as a disambiguator in type deduction, but if it did, that would be the technical reason to use it. Language lawyer, is there a language lawyer on board? :)
Most properly designed projects – even huge ones – should recompile quickly after changes, it’s a matter of proper partitioning of the code and having development builds that leverage such partitioning.
X does not name a type error in C++
When the compiler compiles the class User
and gets to the MyMessageBox
line, MyMessageBox
has not yet been defined. The compiler has no idea MyMessageBox
exists, so cannot understand the meaning of your class member.
You need to make sure MyMessageBox
is defined before you use it as a member. This is solved by reversing the definition order. However, you have a cyclic dependency: if you move MyMessageBox
above User
, then in the definition of MyMessageBox
the name User
won't be defined!
What you can do is forward declare User
; that is, declare it but don't define it. During compilation, a type that is declared but not defined is called an incomplete type.
Consider the simpler example:
struct foo; // foo is *declared* to be a struct, but that struct is not yet defined
struct bar
{
// this is okay, it's just a pointer;
// we can point to something without knowing how that something is defined
foo* fp;
// likewise, we can form a reference to it
void some_func(foo& fr);
// but this would be an error, as before, because it requires a definition
/* foo fooMember; */
};
struct foo // okay, now define foo!
{
int fooInt;
double fooDouble;
};
void bar::some_func(foo& fr)
{
// now that foo is defined, we can read that reference:
fr.fooInt = 111605;
fr.foDouble = 123.456;
}
By forward declaring User
, MyMessageBox
can still form a pointer or reference to it:
class User; // let the compiler know such a class will be defined
class MyMessageBox
{
public:
// this is ok, no definitions needed yet for User (or Message)
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message>* dataMessageList;
};
class User
{
public:
// also ok, since it's now defined
MyMessageBox dataMsgBox;
};
You cannot do this the other way around: as mentioned, a class member needs to have a definition. (The reason is that the compiler needs to know how much memory User
takes up, and to know that it needs to know the size of its members.) If you were to say:
class MyMessageBox;
class User
{
public:
// size not available! it's an incomplete type
MyMessageBox dataMsgBox;
};
It wouldn't work, since it doesn't know the size yet.
On a side note, this function:
void sendMessage(Message *msg, User *recvr);
Probably shouldn't take either of those by pointer. You can't send a message without a message, nor can you send a message without a user to send it to. And both of those situations are expressible by passing null as an argument to either parameter (null is a perfectly valid pointer value!)
Rather, use a reference (possibly const):
void sendMessage(const Message& msg, User& recvr);
Related Topics
Read File Names from a Directory
Compiling a Win32 Gui App (Without a Console) Using Mingw and Eclipse
Where Are Member Functions Stored for an Object
What Are Good Practices Regarding Shared Libraries on Linux
Setjmp/Longjmp: Why Is This Throwing a Segfault
How to Find Out If a Tuple Contains a Type
C++ - <Unresolved Overloaded Function Type>
Why Does Reallocating a Vector Copy Instead of Moving the Elements
Is There C/C++ Equivalent of Eval("Function(Arg1, Arg2)")
How to Use a C++ Smart Pointers Together with C's Malloc
How to Declare Variables of Different Types in the Initialization of a for Loop
How to Enable Experimental C++11 Concurrency Features in Mingw
Calculate Mean and Standard Deviation from a Vector of Samples in C++ Using Boost
What Is _Declspec and When Do I Need to Use It
How to Use the Priority Queue Stl for Objects