...
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; } } |
...