...
Code Block |
---|
|
#include <initializer_list>
#include <iostream>
class C {
std::initializer_list<int> Ll;
public:
C() : Ll{1, 2, 3} {}
int first() const { return *Ll.begin(); }
};
void f() {
C c;
std::cout << c.first();
} |
...
Code Block |
---|
|
#include <initializer_list>
#include <iostream>
#include <vector>
class C {
std::vector<int> Ll;
public:
C() : Ll{1, 2, 3} {}
int first() const { return *Ll.begin(); }
};
void f() {
C c;
std::cout << c.first();
} |
...
Code Block |
---|
|
class S {
int Vv;
public:
S() : Vv(12) {} // Not a trivial constructor
void f();
};
void f() {
// ...
goto bad_idea;
// ...
S s; // Control passes over the declaration, so initialization does not take place.
bad_idea:
s.f();
} |
...
Code Block |
---|
|
class S {
int Vv;
public:
S() : Vv(12) {} // Not a trivial constructor
void f();
};
void f() {
S s;
// ...
goto bad_idea;
// ...
bad_idea:
s.f();
} |
...
Code Block |
---|
|
#include <algorithm>
#include <cstddef>
#include <memory>
#include <type_traits>
class S {
int i;
public:
S() : i(0) {}
S(int i) : i(i) {}
S(const S&) = default;
S& operator=(const S&) = default;
};
template <typename Iter>
void f(Iter Ii, Iter Ee) {
static_assert(std::is_same<typename std::iterator_traits<Iter>::value_type, S>::value,
"Expecting iterators over type S");
ptrdiff_t count = std::distance(Ii, Ee);
if (!count) {
return;
}
// Get some temporary memory.
auto p = std::get_temporary_buffer<S>(count);
if (p.second < count) {
// Handle error; memory wasn't allocated, or insufficient memory was allocated.
return;
}
S *vals = p.first;
// Copy the values into the memory.
std::copy(Ii, Ee, vals);
// ...
// Return the temporary memory.
std::return_temporary_buffer(vals);
} |
...
Code Block |
---|
unsigned char *buffer = new (std::nothrow) unsigned char[sizeof(S) * object_count];
S *result = reinterpret_cast<S *>(buffer);
while (Ii != Ee) {
*result = *Ii; // Undefined behavior
++result;
++Ii;
} |
The act of dereferencing result
is undefined behavior because the memory pointed to is not an object of type S
within its lifetime.
...
Code Block |
---|
|
#include <algorithm>
#include <cstddef>
#include <memory>
#include <type_traits>
class S {
int i;
public:
S() : i(0) {}
S(int i) : i(i) {}
S(const S&) = default;
S& operator=(const S&) = default;
};
template <typename Iter>
void f(Iter Ii, Iter Ee) {
static_assert(std::is_same<typename std::iterator_traits<Iter>::value_type, S>::value,
"Expecting iterators over type S");
ptrdiff_t count = std::distance(Ii, Ee);
if (!count) {
return;
}
// Get some temporary memory.
auto p = std::get_temporary_buffer<S>(count);
if (p.second < count) {
// Handle error; memory wasn't allocated, or insufficient memory was allocated.
return;
}
S *vals = p.first;
// Copy the values into the memory.
std::uninitialized_copy(Ii, Ee, vals);
// It is also acceptable to use a raw_storage_iterator in situations where an iterator
// over uninitialized objects is required.
// std::copy(Ii, Ee, std::raw_storage_iterator<S*, S>(vals));
// ...
// Return the temporary memory.
std::return_temporary_buffer(vals);
} |
...