dcl52 不遵从规范的示例代码 遵从规范的解决方案 风险评估 参考书目 参考链接

C++不允许改变引用类型的类型值,相当于对将所有的引用都用const修饰。C++标准[dcl.ref]第1段[ISO/IEC 14882-2014]阐述如下:

cv限定符修饰的引用是不正确的,通过使用typedef-name(7.1.3,14.1)或dectype-specifier引入的cv限定符除外,这两种情况下cv限定符会被忽略。

所以,C++禁止或忽略引用类型的cv限定符。只有非引用类型可以被cv限定符修饰。

当在引用类型中试图使用const修饰符时,程序员很容易写成下面这样的代码:

char &const p;

而不是这样的代码:

char const &p; // 或者const char& p;

不要用cv限定符去修饰引用类型,这样会导致未定义的行为
符合规范的编译器会对此发出诊断信息
但是,如果编译器没有发出致命诊断信息,程序可能会产生奇怪的结果,
比如p所指向的字符变量被修改。

在下面这个不遵从规范的示例代码中,创建了一个指向char的用const修饰的引用,而不是一个指向用const修饰的char的引用。 这样会导致未定义的行为。

#include <iostream>
 
void f(char c) {
  char &const p = c;
  p = 'p';
  std::cout << c << std::endl;
}

实现细节(MSVC)

Microsoft Visio Studio 2015中,这段代码能够编译通过,但会产生如下警告信息:

warning C4227: anachronism used : qualifiers on reference are ignored

程序运行时,输出结果:

p

实现细节(Clang)

Clang 3.9中,这段代码产生致命信息:

error: ‘const’ qualifier may not be applied to a reference

不遵从规范的示例代码

下面这个不遵从规范的代码,正确地将p声明为一个指向由const的修饰的char变量的引用。
但是后面修改p的值导致程序不正确

#include <iostream>
 
void f(char c) {
  const char &p = c;
  p = 'p'; // 错误: 只读变量不能被赋值
  std::cout << c << std::endl;
}

遵从规范的解决方案

下面这个遵从规范的解决方案删除了const限定符。

#include <iostream>
 
void f(char c) {
  char &p = c;
  p = 'p';
  std::cout << c << std::endl;
}

风险评估

由const或volatile修饰引用类型时,如果不产生致命信息,就会导致未定义的行为,引起非预期的值被存储,以及可能破坏数据完整性。

规则 严重性 可能性 修复代价 优先级 等级
DCL52-CPP 不太可能 P3 L3

自动检测

相关漏洞

参考书目

[Dewhurst 2002] Gotcha #5, “Misunderstanding References”
[ISO/IEC 14882-2014] Subclause 8.3.2, “References”

参考链接

DCL52-CPP. Never qualify a reference type with const or volatile

知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。