Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

References are very similar to pointers. A compiler may substitute pointers for references while compiling a program , and references are often considered a safer data structure than pointers. However, C++ imposes several limitations on references. In particular, C++ does not allow you to change which memory the value of a reference points to. Thus, type, effectively treating all references are effectively as being const references.

Inexperienced programmers are therefore tempted to write:

Code Block
bgColor#ffcccc
langcpp
  char &const p;

instead of:

Code Block
bgColor#ccccff
langcpp
  char const& p;

If the compiler does not complain of the const reference, the program might be compiled and run and produce surprising results. This is because the first form still allows you to change the character pointed at by p, while the second does not.

In fact, qualified. The C++ Standard, [dcl.ref] paragraph 1 [ISO/IEC 14882-20032014] says, in section 8.3.2 "References", states:

Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through introduced through the use of a typedef-name (7.1.3) or of a template type argument (14.3, 14.1) or decltype-specifier (7.1.6.2), in which case the cv-qualifiers are qualifiers are ignored.

Consequently, some compilers do not flag const references.

[Dewhurst 02] Gotcha #5, "Misunderstanding References" says:

...

Thus, C++ prohibits or ignores the cv-qualification of a reference type. Only a value of reference type may be cv-qualified.

When attempting to const-qualify a value of reference type, a programmer may accidentally write:

Code Block
bgColor#ffcccc
langcpp
char &const p;

instead of:

Code Block
bgColor#ccccff
langcpp
char const &p; // or: const char &p;

Do not attempt to cv-qualify a reference type as it can result in undefined behavior. A conforming compiler is required to issue a diagnostic message. However, if the compiler does not emit a fatal diagnostic, the program may produce surprising results, such as allowing the character referenced by p to be mutated.

Noncompliant Code Example

In this noncompliant code , the character, which happens to point to a string literal, is accessed by a reference. The reference itself is const, but the pointed-to data is not. Consequently it is possible to modify the data via the reference.example, a const-qualified reference to a char is formed instead of a reference to a const-qualified char, resulting in undefined behavior:

Code Block
bgColor#ffcccc
langcpp
#include <iostream>
 
void f(char c) = 'c';
{
  char &const p = c;
  p = 'p';
  std::cout << c << std::endl;

...



}

Implementation Details

On With Microsoft Visual C++Studio 2013, this code compiles successfully with a warning diagnostic (warning C4227: anachronism used : qualifiers on reference are ignored) and outputs:

Code Block
p

G++ version 4.2.4 refuses to compile the code, complainingWith Clang 3.5, this code produces a fatal diagnostic:

Code Block
: error: 'const' qualifier qualifiersmay cannotnot be applied to 'char&'a reference

Compliant Solution

If constant reference is required (and the data may be modified via this variable), instead of using a const reference, one can use a const pointerThis compliant solution assumes the programmer intended for the previous example to fail to compile due to attempting to modify a const-qualified char reference:

Code Block
bgColor#ccccff
langcpp
#include <iostream>
 
void f(char c) {
 = 'c';
const char *&p = &c;
*  p = 'p'; // causes compiler error
cout << c << endl;

Compliant Solution

References are still safer than pointers, so a reference to a const value is the best solution when feasible.

Code Block
bgColor#ccccff
langcpp
char c = 'c';
const char &p = c;
p = 'p'; // causes compiler error
, read-only variable is not assignable
  std::cout << c << std::endl;
}

Risk Assessment

Const and volatile references may be freely ignored by the compilerconst and volatile reference types may result in undefined behavior instead of a fatal diagnostic, causing unexpected values to be stored and leading to possible data integrity violations.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

DCL33-CPP

low

unlikely

mediumlow

P2P1

L3

Automated Detection

Tool

Version

Checker

Description

 PRQA QA-C++

 
Include Page
PRQA QA-C++_v
PRQA QA-C++_v

14

 

 

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Bibliography

[ISO/IEC 14882-2014]8.3.2, "References"
[Dewhurst 02]Gotcha #5, "Misunderstanding References"

...

[ISO/IEC 14882-2003]
[Cline 09]]DCL32-CPP. Do not declare or define a reserved identifier      02002. Declarations and Initialization (DCL)      DCL34DCL20-CPP. Use volatile for data that cannot be cached