Безопасно ли использовать memmove / memcpy для инициализации объекта с параметрами конструктора?
Никто, кажется, не использует этот метод, но он отлично работает, когда я попробовал.
Передают ли параметры в стеке проблемы?
Скажи у меня класс foo
следующее,
class foo
{
int x,y;
float z;
foo();
foo(int,int,float);
};
Могу ли я инициализировать переменные с помощью memmove следующим образом?
foo::foo(int x,int y,float z)
{
memmove(this,&x, sizeof(foo));
}
Это неопределенное поведение.
Показанный код не пытается инициализировать переменные класса. Пытается memmove
() на указатель класса и предполагает, что размер класса 2*sizeof(int)+sizeof(float)
, Стандарт C ++ не гарантирует этого.
Кроме того, показанный код также предполагает, что расположение параметров, передаваемых в конструктор, будет таким же, как расположение элементов этого POD
, Это, опять же, не указано в стандарте C ++.
Это безопасно использовать memmove
инициализировать отдельных учеников. Например, следующее безопасно:
foo::foo(int x_,int y_,float z_)
{
memmove(&x, &x_, sizeof(x));
memmove(&y, &y_, sizeof(y));
memmove(&z, &z_, sizeof(z));
}
Конечно, это ничего не дает, но это будет безопасно.
Нет, это небезопасно, потому что в соответствии со стандартом членам не гарантируется немедленно сразу после друг друга из-за выравнивания / дополнения.
После вашего обновления это еще хуже, поскольку расположение передаваемых аргументов и их порядок небезопасны для использования.
Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация — корень всего зла. Тем не менее, мы не должны упускать наши возможности в этих критических 3%. — Дональд Кнут
Вы не должны пытаться оптимизировать код, который вам не нужен. Я бы предложил вам профиль вашего кода прежде чем вы сможете выполнить этот вид оптимизации. Таким образом, вы не теряй время улучшение производительности некоторого кода, который не собирается влиять на общую производительность вашего приложения.
Обычно компиляторы достаточно умны, чтобы угадать, что вы пытаетесь сделать с вашим кодом, и генерируют высокоэффективный код, который будет сохранять ту же функциональность. Для этого вы должны быть уверены, что вы включаете оптимизацию компилятора (-Olevel
помечать или переключать отдельные через аргументы команды компилятора).
Например, я видел, что некоторые компиляторы преобразуют std::copy
в memcpy, когда компилятор уверен, что сделать это просто (например, данные непрерывны).
Нет, это не безопасно. Это неопределенное поведение.
И код
foo::foo(int x,int y,float z)
{
memmove(this,&x, sizeof(foo));
}
даже не экономит на вводе текста по сравнению со списком инициализаторов
foo::foo(int x,int y,float z) : x(x), y(y), z(z)
{ }