I currently have a function that is meant to return T (templated function). So I always assumed it MUST return a value, but I recently stumbled across something.
#define PRINTERROR(msg) \
std::cout << msg << "\n\tFILE: " << __FILE__ << "\n\tLINE: " << __LINE__ << "\n\tTIME: " << __TIME__ << std::endl << std::endl;
and this...
template<class T>
T& Container_Vector<T>::GetFirstItem()
{
#ifdef CONTAINER_VECTOR_ERROR_CHECKING_ON
if (m_iCurrentSize > 0)
{
return m_pItems[0];
}
else
{
PRINTERROR("ERROR: Attempting to retrieve item from an empty vector container");
}
#else
return m_pItems[0];
#endif
}
When I step through the code trying to test if the msg gets outputted and error checking is on the first check(m_iCurrentSize > 0) fails, the message is printed and then it appears to jump to the end of the function "}" and return nothing?
Usually I'd get a compile error saying it has to return something. What's going on here and is it ok?
While it doesn't actually step through onto a开发者_JAVA百科nything that returns T it does return something, a random memory address maybe.
You are missing a return
after the PRINTERROR
in the #ifdef
block. Not doing so results in an undefined behavior. You must return an appropriate value at the end of the function.
(Such logical error can be caught at compile time with appropriates flags set. For example, in g++ you can use -Wall
.)
First of all, the preprocessing takes place before the compilation. To your compiler, the code looks like -
If CONTAINER_VECTOR_ERROR_CHECKING_ON
is defined:
template<class T>
T& Container_Vector<T>::GetFirstItem()
{
if (m_iCurrentSize > 0)
{
return m_pItems[0];
}
else
{
PRINTERROR("ERROR: Attempting to retrieve item from an empty vector container");
}
}
if CONTAINER_VECTOR_ERROR_CHECKING_ON
is NOT defined:
template<class T>
T& Container_Vector<T>::GetFirstItem()
{
return m_pItems[0];
}
Your first case doesn't have a return on all branches, you should get a warning at least. MSVS doesn't report a compilation error, but it does return a warning. The random number you're getting is simply the last value present in the return register before the function exits.
Omitting to return a value from a function unfortunately is not a compile error.
A compiler may emit a diagnostic message (for example g++ does if compiling with -Wall
option) but it's not mandatory.
Omitting to return a value is something that compiler writers are free to assume a programmer will never do, and if a program does it the standard says that the compiler is free to ignore the problem and whatever happens happens (undefined behavior). It's always a programmer fault.
On x86 architecture normally the net effect is just that you will get some strange value if the function is returning a true "native" type (e.g. a char
or an int
) that fits in a register and you may instead get memory corruption or a crash if the function is for example returning a class instance (e.g. std::string
). Note however that any speculation about what happens in case of undefined behavior is just that... i.e. pure speculation as indeed anything may happen for the C++ language specification.
That's undefined behavior, if CONTAINER_VECTOR_ERROR_CHECKING_ON
is defined and !( m_iCurrentSize > 0 )
then you are not returing anything. You may get a warning, but not an error since you do have one conditional return
. In such case the function returns garbage, and the stack is probably corrupted after that.
精彩评论