kakker: я, конечно, извиняюсь, но та функция, которую вы привели, выглядит, как говнокод. Расскажите подробнее, что вам надо сделать на более высоком уровне и какую роль во всем этом играет приведенная функция.
sitev_ru: Ещё до начала работы конструктора все поля класса уже обязаны быть инициализированы. Если мы не добавим такие инициализаторы, то компилятор инициализирует из за нас конструктором по умолчанию, то есть будет выполнять дополнительную работу в рантайме.
P.S. Встроенные типы можно оставить неинициализированными, но это плохая практика.
Xano: Не обязательно POD. Я говорю об операторе присваивания. Вот так сделать не получится:
AnnType a(...), b(...);
a = std::move(b);
Даже если Joe никогда это не понадобится, Ann может понадобиться, например, отсортировать вектор из AnnType. Ну и дальше пояснение выше.
Xano: Копировать ссылки не запретили, зато всё, что содержит ссылки, нельзя присваивать.
struct JoeType { int& field; };
struct AnnType { JoeType field; };
Если теперь Ann понадобится присваивать AnnType, то она точно будет сердиться на Joe за то, что он использовал ссылку вместо указателя. Можно содержать std::unique_ptr, но ведь этих проблем изначально можно было бы избежать.
матрунич сергей: Формально, отличие в типе массива: int[3][3] и int*[3]. Теперь неформально. Ваш массив представлен в памяти как 3 идущих последовательно int[3], то есть m2d у вас -- это 9 последовательных int. Функция же принимает массив, содержащий 3 указателя int* (принципиально другой тип данных!). Каждый из них должен указывать на массив из 3 int. Понятно, что функция, принимающая 3 указателя (которые, так получилось, указывают на массивы), не может "съесть" 9 int.
матрунич сергей: Если заданы такие прототипы и массив строго 3x3, то как-то так:
int row1[3] = {1,2,3};
int row2[3] = {4,5,6};
int row3[3] = {0,2,6};
int* m2d[3] = {row1,row2,row3};
function(m2d,3,3);
матрунич сергей: Многомерные массивы бывают разные. int** -- массив указателей на массивы, его можно передавать так, как у вас. А вот int(*)[3] (тип m2d) -- хранится непрерывно. Если размер неизвестен на этапе компиляции, то лучше передать указатель на первый элемент int* плюс размерности. Если известен, то можно принять параметр функции int m2d[3][3].
Xano: Типы с хранимыми ссылками не будут ни CopyAssignable, ни MoveAssignable. Обычно это ограничение обходят, используя указатели вместо ссылок для полей.
std::shared_ptr -- неправильно выразился. Хотел сказать, что std::unique_ptr должен использоваться по умолчанию для хранения полиморфных и "тяжелых" объектов. Проще удалить абзац, чем написать нормально :)
Петр: Понятно, что 4 байта лучше передать по значению, а 1000 байт -- по ссылке. Истина где-то посередине. Они показали, что на некоторых архитектурах эта истина -- 32 байта.
матрунич сергей: Всё-таки вы не доучили теорию :) Экземпляр передаётся в метод неявно через this, а вот если нужно оперировать сразу с двумя объектами одного типа, тогда нужно объявление, как у вас в getData.
Павел Каптур: Пусть вы пишите функцию C++ и хотите принять тип T в качестве параметра. Варианты:
1) Если T -- простой тип меньше 32 байт (int, double, маленькие структуры), передавайте по значению: T name
2) Если можно обойтись без изменения значения параметра, передавайте по константной ссылке: const T& name
3) Если без изменения значения параметра никак не обойтись, передавайте по ссылке: T& name
Ссылка -- это указатель, который автоматически разыменовывается.