The following code compiles without any errors/warnings with gcc 6.3 (https://godbolt.org/g/sVZ8OH), but it contains a dangerous undefined behavior due to invalid memory access marked below. The root cause is the implicit conversion performed in emplace_back. Can anyone suggest a good way or best practices to avoid such bugs in code?
#include <iostream>
#include <vector>
struct Foo
{
explicit Foo(const int& i) : i{i} {}
void foo() const { std::cout << i; } // invalid memory access, as i is an invalid ref!!
const int& i;
};
void bar(const double& d) {
std::vector<Foo> fv;
fv.emplace_back(d);
}
If you are going to accept a const reference, but you don't want a reference to a temporary, declare an additional constructor with an rvalue reference argument - and delete it.
struct Foo
{
explicit Foo(const int& i) : i{i} {}
explicit Foo(const int&& i) = delete; // This preferentially matches a reference to a
// temporary, and compilation fails.
void foo() const { std::cout << i; } // invalid memory access, as i is an invalid ref!!
const int& i;
};
(I am assuming that the actual problem is more complex than just an int. For an int, holding it by value is the right answer.)
Can anyone suggest a good way or best practices to avoid such bugs in code?
When your class stores a const
reference to another object, you, as a programmer, are taking on the responsibility of making sure that you don't end up storing a dangling reference.
Unless you have a strong reason for storing a const
reference, I would recommend storing a value.
struct Foo
{
explicit Foo(const int& i) : i{i} {}
void foo() const { std::cout << i; }
int i;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With