// MAIN.CPP
#include <iostream>
#include "tmpl.h"
void doFile1();
int main()
{
const char* x = "main";
outThing(x);
doFile1();
return 0;
}
// FILE1.CPP
#include "tmpl.h"
void doFile1()
{
const char* x = "doFile1";
outThing(x);
}
// TMPL.H
#pragma once
#include <iostream>
template <class T>
void outThing(const T& x)
{
std::cout << "The thing is " << x << std::endl;
}
Discarded input sections
.text$_Z8outThingIPKcEvRKT_
0x0000000000000000 0x50 debug/main.o
Linker script and memory map
.text$_Z8outThingIPKcEvRKT_
0x0000000140002900 0x50 debug/file1.o
0x0000000140002900 void outThing<char const*>(char const* const&)
Ну и ещё парочка структур для раскрутки стека и подстановки адресов…
double s = 0;
for (i...) {
s += Sum(m, &a[i][0]);
}
Если переменных в памяти потребуется слишком большое количество, которое не сможет вместить в себя сама аппаратная часть, произойдет перегрузка системы или её зависание.
Можете себе представить, если бы небезызвестная Battlefield 3 использовала такой метод работы с данными? В таком случае, самым заядлым геймерам пришлось бы перезагружать свои высоконагруженные системы кнопкой reset после нескольких секунд работы игры.
Если не уничтожать неиспользуемые объекты, очень скоро они заполнят весь объем ресурсов ПК.
#include <iostream>
union DoubleInt {
double asDouble;
uint64_t asInt;
};
static_assert(sizeof(double) == sizeof(uint64_t), "Strange machine with double != int64");
constexpr int BITS_MANTISSA = 52;
constexpr int BITS_EXPONENT = 11;
constexpr int BITS_SIGN = 1;
static_assert(BITS_MANTISSA + BITS_EXPONENT + BITS_SIGN == 64, "Programmer's funkup");
constexpr uint64_t MANTISSA_UNIT = uint64_t(1) << BITS_MANTISSA;
constexpr uint64_t MANTISSA_MASK = MANTISSA_UNIT - 1;
constexpr int EXPONENT_SHIFT = BITS_MANTISSA;
constexpr uint64_t EXPONENT_MAX = (uint64_t(1) << BITS_EXPONENT) - 1;
constexpr uint64_t EXPONENT_ORIGIN = EXPONENT_MAX >> 1;
constexpr uint64_t EXPONENT_MASK = EXPONENT_MAX << EXPONENT_SHIFT;
constexpr uint64_t EXPONENT_SHIFTED_ORIGIN = EXPONENT_ORIGIN << EXPONENT_SHIFT;
constexpr int SIGN_SHIFT = BITS_MANTISSA + BITS_EXPONENT;
constexpr uint64_t SIGN_MASK = uint64_t(1) << SIGN_SHIFT;
int main()
{
DoubleInt x { -3.45 };
// Простите уж, без денормализованных чисел
// Оставим знак и мантиссу
DoubleInt xMantissa = x;
xMantissa.asInt &= (MANTISSA_MASK | SIGN_MASK);
// И добавим туда стандартный нулевой порядок
xMantissa.asInt |= EXPONENT_SHIFTED_ORIGIN;
// Извлечём порядок
int exponent = ((x.asInt & EXPONENT_MASK) >> EXPONENT_SHIFT) - EXPONENT_ORIGIN;
std::cout << xMantissa.asDouble << "*2^" << exponent << std::endl;
return 0;
}
wiTile->~WiTile();
new (wiTile) WiTile(client(), icons, clazz, tileSettings(i));
не удается преобразовать 'char*' в 'int*' для аргумента '1' в 'int
недопустимое преобразование из 'int*' в 'int'
warning: narrowing conversion of '143' from 'int' to 'char' inside
const struct s & ref = f();
struct s && ref = f();
void modify(s& arg) { ++arg[1]; }
...
modify(f());
namespace Addresses {
uintptr_t myAddresses = processManager.xxx;
}
namespace Addresses {
extern uintptr_t myAddresses;
}
size_t str::replace(
std::string& aString,
const char aWhat,
const char aByWhat)
{
size_t r = 0;
FOR_S(i, 0, aString.length())
if (aString[i] == aWhat) {
aString[i] = aByWhat;
++r;
}
return r;
}
size_t str::replace(
std::string &aString,
char aWhat,
CONST_STR aByWhat)
{
if (aByWhat.length()==1)
{ // Simple replace
return str::replace(aString, aWhat, aByWhat[0]);
}
// More complex replace
static const size_t szWhat = 1;
const size_t szByWhat = aByWhat.length();
size_t p = 0, r = 0;
while ((p = aString.find(aWhat, p)) != std::string::npos)
{
aString.replace(p, szWhat, aByWhat);
p += szByWhat;
++r;
}
return r;
}
#include <iostream>
class Wrap
{
public:
Wrap(int x) : value(x) {}
private:
int value;
template <class T>
friend void out(const T&);
};
template <>
void out(const Wrap& x)
{ std::cout << x.value << std::endl; }
int main()
{
Wrap x(42);
out(x);
return 0;
}
#include <iostream>
namespace qq {
template <class T>
void out(const T&);
}
class Wrap
{
public:
Wrap(int x) : value(x) {}
private:
int value;
template <class T>
friend void qq::out(const T&);
};
template <>
void qq::out(const Wrap& x)
{ std::cout << x.value << std::endl; }
int main()
{
Wrap x(42);
qq::out(x);
return 0;
}
char* text = "foo";
, а разработка Си(++) застопорилась на десятилетие, учебники по Си очень долго писали такую нерекомендуемую строчку.#include <iostream>
class WrapInt
{
public:
int value = 0;
WrapInt(int x) : value(x) {}
WrapInt(WrapInt&) = delete;
private:
};
int main()
{
WrapInt x = 42;
}
int zero = 0;
до C++14 — создать временный объект, вызвать конструктор перемещения, а остальное делает оптимизатор. С Си++17 — вызов конструктора, если он не explicit. Мне казалось, что в очень старых версиях DJGPP был задействован op=, но ХЕЗ, MinGW и Си++03 вызывают именно конструктор.int zero = int(0);
— что удивительно, то же самое, только конструктор любой! Хотя выглядит как явное создание временного объекта.int zero(0);
— вызов конструктора во всех версиях Си++.int zero{0};
— универсальный инициализатор Си++11, также вызов конструктора.int array[] = { 1, 2, 3};
— все версии Си и Си++. int array[] { 1, 2, 3};
— универсальный инициализатор Си++11.array[b] = newElem; ++b;
. Керниган и Ритчи решили объединить это чудо в одну строку array[b++] = newElem;
, к тому же в процессорах действительно бывают пред- и постинкрементные операции.std::string helloWorld(std::move(hello().operator std::string()));