Jawaban:
Makro preprocessor hanyalah pola substitusi yang diterapkan ke kode Anda. Mereka dapat digunakan hampir di mana saja dalam kode Anda karena diganti dengan perluasannya sebelum kompilasi dimulai.
Fungsi sebaris adalah fungsi aktual yang tubuhnya disuntikkan langsung ke situs panggilannya. Mereka hanya dapat digunakan jika pemanggilan fungsi sesuai.
Sekarang, sejauh menggunakan makro vs. fungsi sebaris dalam konteks mirip fungsi, perhatikan bahwa:
Pertama, makro preprocessor hanya "copy paste" di kode sebelum kompilasi. Jadi tidak ada pemeriksaan tipe , dan beberapa efek samping bisa muncul
Misalnya, jika Anda ingin membandingkan 2 nilai:
#define max(a,b) ((a<b)?b:a)
Efek samping muncul jika Anda menggunakan max(a++,b++)
misalnya ( a
atau b
akan bertambah dua kali). Sebagai gantinya, gunakan (misalnya)
inline int max( int a, int b) { return ((a<b)?b:a); }
max(fibonacci(100), factorial(10000))
yang lebih besar akan dihitung dua kali :(
Fungsi Inline diperluas oleh compiler dimana makro diperluas oleh Preprocessor, yang merupakan substitusi tekstual belaka.
Tidak ada pemeriksaan jenis selama pemanggilan makro sementara pemeriksaan jenis dilakukan selama pemanggilan fungsi.
Hasil dan inefisiensi yang tidak diinginkan dapat terjadi selama ekspansi makro karena evaluasi ulang argumen dan urutan operasi. Sebagai contoh
#define MAX(a,b) ((a)>(b) ? (a) : (b))
int i = 5, j = MAX(i++, 0);
akan menghasilkan
int i = 5, j = ((i++)>(0) ? (i++) : (0));
Argumen makro tidak dievaluasi sebelum perluasan makro
#define MUL(a, b) a*b
int main()
{
// The macro is expended as 2 + 3 * 3 + 5, not as 5*8
printf("%d", MUL(2+3, 3+5));
return 0;
}
// Output: 16`
Kata kunci return tidak dapat digunakan dalam makro untuk mengembalikan nilai seperti pada kasus fungsi.
Fungsi sebaris dapat kelebihan beban
Token yang diteruskan ke makro bisa digabungkan menggunakan operator ## yang disebut operator Token-Pasting.
Makro umumnya digunakan untuk penggunaan kembali kode di mana fungsi inline digunakan untuk menghilangkan overhead waktu (waktu berlebih) selama pemanggilan fungsi (menghindari lompatan ke subrutin).
Perbedaan utamanya adalah pemeriksaan tipe. Kompilator akan memeriksa apakah yang Anda berikan sebagai nilai masukan adalah jenis yang dapat diteruskan ke fungsi. Itu tidak benar dengan makro praprosesor - mereka diperluas sebelum pemeriksaan jenis apa pun dan itu dapat menyebabkan bug yang parah dan sulit dideteksi.
Berikut adalah beberapa poin lain yang kurang jelas diuraikan.
Untuk menambahkan perbedaan lain ke yang sudah diberikan: Anda tidak bisa melangkah melalui #define
di debugger, tapi Anda bisa melangkah melalui fungsi sebaris.
Makro mengabaikan ruang nama. Dan itu membuat mereka jahat.
fungsi sebaris mirip dengan makro (karena kode fungsi diperluas pada titik panggilan pada waktu kompilasi), fungsi sebaris diurai oleh kompilator, sedangkan makro diperluas oleh preprocessor. Akibatnya, ada beberapa perbedaan penting:
Dalam beberapa kasus, ekspresi yang diteruskan sebagai argumen ke makro bisa dievaluasi lebih dari sekali. http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx
makro diperluas pada waktu pra-kompilasi, Anda tidak dapat menggunakannya untuk debugging, tetapi Anda dapat menggunakan fungsi sebaris.
- artikel bagus : http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1
;
Fungsi inline akan mempertahankan semantik nilai, sedangkan makro preprocessor hanya menyalin sintaksnya. Anda bisa mendapatkan bug yang sangat halus dengan makro preprocessor jika Anda menggunakan argumen beberapa kali - misalnya jika argumen berisi mutasi seperti "i ++" yang mengeksekusi dua kali cukup mengejutkan. Fungsi sebaris tidak akan mengalami masalah ini.
Untuk mengetahui perbedaan antara fungsi makro dan sebaris , pertama-tama kita harus mengetahui apa itu sebenarnya dan kapan kita harus menggunakannya.
FUNGSI :
int Square(int x){
return(x*X);
}
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
Pemanggilan fungsi memiliki overhead yang terkait dengannya, karena setelah fungsi selesai dieksekusi, ia harus tahu ke mana ia harus kembali dan juga perlu menyimpan nilai dalam memori tumpukan.
Untuk aplikasi kecil tidak akan menjadi masalah, tetapi mari kita ambil contoh aplikasi keuangan di mana ribuan transaksi terjadi setiap detik, kita tidak bisa menggunakan pemanggilan fungsi.
MACROS:
# define Square(x) x*x;
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
hasil int = Persegi (x * x)
Tetapi makro memiliki bug yang terkait dengannya.
#define Square(x) x*x
int main() {
int val = 5;
int result = Square(val + 1);
cout << result << endl;
return 0;
}
Di sini outputnya 11 bukan 36 .
FUNGSI INLINE :
inline int Square(int x) {
return x * x;
}
int main() {
using namespace std;
int val = 5;
int result = Square(val + 1);
cout << result << endl;
return 0;
}
Hasil 36
Kata kunci inline meminta kompilator untuk mengganti pemanggilan fungsi dengan tubuh fungsi, di sini keluarannya benar karena ia mengevaluasi ekspresi terlebih dahulu dan kemudian diteruskan. Ini mengurangi overhead panggilan fungsi karena tidak perlu menyimpan alamat yang dikembalikan dan tumpukan memori tidak diperlukan untuk argumen fungsi.
Perbandingan Antara Makro dan Fungsi Inline:
KESIMPULAN:
Fungsi sebaris terkadang lebih berguna daripada makro, karena meningkatkan kinerja dan aman digunakan serta mengurangi overhead panggilan fungsi juga. Ini hanya permintaan ke kompiler, fungsi tertentu tidak akan disebariskan seperti:
yang merupakan hal yang baik, karena itu adalah kapanpun kompilator berpikir lebih baik untuk melakukan sesuatu dengan cara lain.
Di GCC (saya tidak yakin tentang yang lain), mendeklarasikan fungsi sebaris, hanyalah petunjuk bagi kompiler. Terserah pada kompilator di penghujung hari untuk memutuskan apakah ia menyertakan tubuh fungsi kapan pun ia dipanggil.
Perbedaan antara fungsi in-line dan makro preprocessor relatif besar. Makro preprocessor hanyalah pengganti teks di penghujung hari. Anda menyerahkan banyak kemampuan bagi kompilator untuk melakukan pemeriksaan jenis pemeriksaan pada argumen dan jenis kembalian. Evaluasi argumen jauh berbeda (jika ekspresi yang Anda berikan ke fungsi memiliki efek samping, Anda akan bersenang-senang saat debugging). Ada perbedaan halus tentang di mana fungsi dan makro dapat digunakan. Misalnya jika saya memiliki:
#define MACRO_FUNC(X) ...
Di mana MACRO_FUNC dengan jelas mendefinisikan tubuh fungsi. Perhatian khusus perlu diberikan agar berfungsi dengan benar di semua kasus, suatu fungsi dapat digunakan, misalnya MACRO_FUNC yang ditulis dengan buruk akan menyebabkan kesalahan pada
if(MACRO_FUNC(y)) {
...body
}
Fungsi normal dapat digunakan tanpa masalah.
Dari perspektif pengkodean, fungsi sebaris seperti fungsi. Jadi, perbedaan antara fungsi sebaris dan makro sama dengan perbedaan antara fungsi dan makro.
Dari perspektif kompilasi, fungsi sebaris mirip dengan makro. Itu disuntikkan langsung ke dalam kode, tidak dipanggil.
Secara umum, Anda harus mempertimbangkan fungsi inline sebagai fungsi biasa dengan beberapa pengoptimalan kecil yang tercampur. Dan seperti kebanyakan pengoptimalan, terserah pada kompilator untuk memutuskan apakah benar-benar peduli untuk menerapkannya. Seringkali kompilator akan dengan senang hati mengabaikan setiap upaya programmer untuk menyebariskan suatu fungsi, karena berbagai alasan.
Fungsi inline akan berperilaku sebagai pemanggilan fungsi jika terdapat pernyataan berulang atau rekursif di dalamnya, untuk mencegah eksekusi instruksi yang berulang. Ini cukup membantu untuk menyimpan keseluruhan memori program Anda.
#include<iostream>
using namespace std;
#define NUMBER 10 //macros are preprocessed while functions are not.
int number()
{
return 10;
}
/*In macros, no type checking(incompatible operand, etc.) is done and thus use of micros can lead to errors/side-effects in some cases.
However, this is not the case with functions.
Also, macros do not check for compilation error (if any). Consider:- */
#define CUBE(b) b*b*b
int cube(int a)
{
return a*a*a;
}
int main()
{
cout<<NUMBER<<endl<<number()<<endl;
cout<<CUBE(1+3); //Unexpected output 10
cout<<endl<<cube(1+3);// As expected 64
return 0;
}
Makro biasanya lebih cepat daripada fungsi karena tidak melibatkan overhead panggilan fungsi yang sebenarnya.
Beberapa Kekurangan dari makro: Tidak ada pemeriksaan tipe. Sulit untuk melakukan debug karena menyebabkan penggantian yang sederhana. Makro tidak memiliki namespace, jadi makro di satu bagian kode dapat mempengaruhi bagian lain. Makro dapat menyebabkan efek samping seperti yang ditunjukkan pada contoh CUBE () di atas.
Makro biasanya satu baris. Namun, mereka dapat terdiri dari lebih dari satu baris. Tidak ada batasan seperti itu dalam fungsi.
#define TWO_N(n) 2 << n
dan kemudian cout << CUBE(TWO_N(3 + 1)) << endl;
? (Lebih baik mengakhiri baris keluaran endl
daripada memulainya.)