...
Do not use pointer arithmetic, including array subscripting, on polymorphic objects.
Noncompliant Code Example
In this noncompliant code example, f()
accepts an array of S
objects as its first parameter. However, main()
passes an array of T
objects as the first argument to f()
, which results in undefined behavior due to the pointer arithmetic used within the for
loop.
The following code examples assume the following static variables and class definitions:
Code Block | ||||
---|---|---|---|---|
Code Block | ||||
| ||||
#include <iostream>
int globI;
double globD;
struct S {
int i;
S() : i(globI++) {}
};
struct T : S {
double d;
T() : S(), d(globD++) {}
}; |
Noncompliant Code Example
In this noncompliant code example, f()
accepts an array of S
objects as its first parameter. However, main()
passes an array of T
objects as the first argument to f()
, which results in undefined behavior due to the pointer arithmetic used within the for
loop.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> // ... definitions for S, T, globI, globD ... void f(const S *someSes, std::size_t count) { for (const S *end = someSes + count; someSes != end; ++someSes) { std::cout << someSes->i << std::endl; } } int main() { T test[5]; f(test, 5); } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> int globI; double globD; struct S { int i; S() : i(globI++) {} }; struct T : S { double d; T() : S(), d(globD++) {} }; // ... definitions for S, T, globI, globD ... void f(const S * const *someSes, std::size_t count) { for (const S * const *end = someSes + count; someSes != end; ++someSes) { std::cout << (*someSes)->i << std::endl; } } int main() { S *test[] = {new T, new T, new T, new T, new T}; f(test, 5); for (auto v : test) { delete v; } } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> #include <vector> int globI; double globD; struct S { int i; S() : i(globI++) {} }; struct T : S { double d; T() : S(), d(globD++) {} }; // ... definitions for S, T, globI, globD ... template <typename Iter> void f(Iter i, Iter e) { for (; i != e; ++i) { std::cout << (*i)->i << std::endl; } } int main() { std::vector<S *> test{new T, new T, new T, new T, new T}; f(test.cbegin(), test.cend()); for (auto v : test) { delete v; } } |
...