Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: condensed definitions for S, T, globD, globI

...

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
bgColor#FFCCCC
langcpp
#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
bgColor#FFCCCC
langcpp
#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
bgColor#ccccff
langcpp
#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
bgColor#ccccff
langcpp
#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;
  }
}

...