[c++] ما هي الاختلافات بين متغير مؤشر ومتغير مرجع في C ++؟


Answers

ما هو مرجع C ++ ( للمبرمجين C )

يمكن اعتبار الإشارة كمؤشر ثابت (لا ينبغي الخلط بينه وبين مؤشر لقيمة ثابتة!) مع indirection تلقائي ، أي أن المترجم سيطبق المشغل * أجلك.

يجب أن تتم تهيئة جميع المراجع باستخدام قيمة غير فارغة وإلا فسيخفق التحويل البرمجي. لا يمكن الحصول على عنوان مرجع - حيث سيعيد مشغل العنوان عنوان القيمة المشار إليها بدلاً من ذلك - ولا يمكن القيام بعلم الحساب على المراجع.

قد لا يروق مبرمجو C C لمراجع C ++ لأنه لن يكون واضحًا عند حدوث تفاعل غير مباشر أو إذا تم تمرير وسيطة حسب القيمة أو المؤشر بدون النظر إلى توقيعات الدوال.

قد لا يحب المبرمجون C ++ استخدام المؤشرات لأنهم يعتبرون غير آمنين - على الرغم من أن المراجع ليست في الواقع أكثر أمنا من المؤشرات الثابتة إلا في الحالات الأكثر تافها - يفتقرون إلى الراحة التلقائية غير المباشرة ويحملون دلالة دلالية مختلفة.

خذ بعين الاعتبار العبارة التالية من الأسئلة المتداولة C ++ :

على الرغم من أن المرجع غالباً ما يتم تنفيذه باستخدام عنوان في لغة التجميع الأساسية ، من فضلك لا تفكر في إشارة كمؤشر مضحك المظهر إلى كائن. المرجع هو الكائن. ليس مؤشر إلى الكائن ولا نسخة من الكائن. هذا هو الشيء.

ولكن إذا كان المرجع حقاً كائن ، كيف يمكن أن يكون هناك مراجع متدلية؟ في اللغات غير المُدارة ، من المستحيل أن تكون المراجع أي "أكثر أمانًا" من المؤشرات - فهناك عمومًا طريقة غير موثوقة للقيم المتمايزة عبر حدود النطاق!

لماذا أعتبر مراجع C ++ مفيدة

قد تبدو المراجع C ++ من خلفية C ، وكأنها مفهوم سخيفة إلى حد ما ، ولكن يجب على المرء أن يستخدمها بدلاً من المؤشرات حيثما أمكن: إن التلقائية التلقائية مريحة ، وتصبح المراجع مفيدة بشكل خاص عند التعامل مع RAII - ولكن ليس بسبب أي سلامة مدركة. ميزة ، ولكن لأنها تجعل من كتابة التعليمات البرمجية الاصطلاحية أقل محرجا.

RAII هي واحدة من المفاهيم المركزية لـ C ++ ، ولكنها تتفاعل بشكل غير تافه مع نسخ الدلالات. يتجنب تمرير الكائنات بالإحالة هذه المشكلات نظرًا لعدم مشاركة النسخ. إذا لم تكن المراجع موجودة في اللغة ، فسيتعين عليك استخدام المؤشرات بدلاً من ذلك ، والتي تكون أكثر تعقيدًا للاستخدام ، وبالتالي تنتهك مبدأ تصميم اللغة بأن الحل الأفضل للممارسة يجب أن يكون أسهل من البدائل.

Question

أعرف أن المراجع عبارة عن سكر نحوي ، لذلك من السهل قراءة الكود والكتابة.

لكن ما هي الاختلافات؟

ملخص من الإجابات والروابط أدناه:

  1. يمكن إعادة تعيين المؤشر لأي عدد من المرات في حين لا يمكن إعادة التوثيق بعد الربط.
  2. يمكن أن تشير المؤشرات إلى أي مكان ( NULL ) ، بينما يشير المرجع دائمًا إلى كائن.
  3. لا يمكنك أخذ عنوان مرجع كما يمكنك باستخدام المؤشرات.
  4. لا يوجد "علم حساب مرجعي" (ولكن يمكنك أن تأخذ عنوان كائن مدبب من قبل مرجع ويقوم بعلم الحساب عليه كما في &obj + 5 ).

لتوضيح الاعتقاد الخاطئ:

معيار C ++ حذراً للغاية لتجنب إملاء كيف يجب على المحول البرمجي تطبيق المراجع ، ولكن يقوم كل مترجم C ++ بتنفيذ المراجع كمؤشرات. هذا هو ، إعلان مثل:

int &ri = i;

إذا لم يتم تحسينها تمامًا ، فسيخصص نفس مقدار التخزين كمؤشر ، ويضع عنوان i في هذا التخزين.

لذا ، يشغل كل من المؤشر والمرجع نفس مقدار الذاكرة.

كقاعدة عامة،

  • استخدم المراجع في معلمات الدالة وأنواع الإرجاع لتحديد واجهات مفيدة وتوثيق ذاتي.
  • استخدم المؤشرات لتطبيق الخوارزميات وهياكل البيانات.

قراءة مثيرة للاهتمام:




A reference is an alias for another variable whereas a pointer holds the memory address of a variable. References are generally used as function parameters so that the passed object is not the copy but the object itself.

    void fun(int &a, int &b); // A common usage of references.
    int a = 0;
    int &b = a; // b is an alias for a. Not so common to use. 



The difference is that non-constant pointer variable(not to be confused with a pointer to constant) may be changed at some time during program execution, requires pointer semantics to be used(&,*) operators, while references can be set upon initialization only(that's why you can set them in constructor initializer list only, but not somehow else) and use ordinary value accessing semantics. Basically references were introduced to allow support for operators overloading as I had read in some very old book. As somebody stated in this thread - pointer can be set to 0 or whatever value you want. 0(NULL, nullptr) means that the pointer is initialized with nothing. It is an error to dereference null pointer. But actually the pointer may contain a value that doesn't point to some correct memory location. References in their turn try not to allow a user to initialize a reference to something that cannot be referenced due to the fact that you always provide rvalue of correct type to it. Although there are a lot of ways to make reference variable be initialized to a wrong memory location - it is better for you not to dig this deep into details. On machine level both pointer and reference work uniformly - via pointers. Let's say in essential references are syntactic sugar. rvalue references are different to this - they are naturally stack/heap objects.




Another interesting use of references is to supply a default argument of a user-defined type:

class UDT
{
public:
   UDT() : val_d(33) {};
   UDT(int val) : val_d(val) {};
   virtual ~UDT() {};
private:
   int val_d;
};

class UDT_Derived : public UDT
{
public:
   UDT_Derived() : UDT() {};
   virtual ~UDT_Derived() {};
};

class Behavior
{
public:
   Behavior(
      const UDT &udt = UDT()
   )  {};
};

int main()
{
   Behavior b; // take default

   UDT u(88);
   Behavior c(u);

   UDT_Derived ud;
   Behavior d(ud);

   return 1;
}

The default flavor uses the 'bind const reference to a temporary' aspect of references.




خلافا للرأي الشعبي ، من الممكن أن يكون هناك إشارة NULL.

int * p = NULL;
int & r = *p;
r = 1;  // crash! (if you're lucky)

صحيح أنه من الأصعب القيام بمرجع - ولكن إذا قمت بإدارته ، فسوف تمزق شعرك في محاولة العثور عليه. المراجع ليست آمنة بطبيعتها في C ++!

من الناحية الفنية ، يعد هذا مرجعًا غير صالح ، وليس مرجعًا فارغًا. لا يدعم C ++ المراجع الفارغة كمفهوم كما قد تجده في اللغات الأخرى. هناك أنواع أخرى من المراجع غير الصالحة أيضًا. أي مرجع غير صالح يرفع شبح السلوك غير المعروف ، مثلما يفعل مؤشر غير صحيح.

الخطأ الفعلي في dereferencing مؤشر NULL ، قبل التعيين إلى مرجع. لكنني لست على علم بأي من المجمعين الذين سيولدون أي أخطاء على هذا الشرط - ينتشر الخطأ إلى نقطة أخرى في الشفرة. هذا ما يجعل هذه المشكلة خبيثة جدا. في معظم الأحيان ، إذا قمت بالتعريف عن مؤشر NULL ، فستتحطم على الفور في هذا المكان ولا يتطلب الأمر تصحيحًا كبيرًا حتى يتم اكتشافه.

المثال أعلاه هو قصير ومفتوح. فيما يلي مثال أكثر واقعية.

class MyClass
{
    ...
    virtual void DoSomething(int,int,int,int,int);
};

void Foo(const MyClass & bar)
{
    ...
    bar.DoSomething(i1,i2,i3,i4,i5);  // crash occurs here due to memory access violation - obvious why?
}

MyClass * GetInstance()
{
    if (somecondition)
        return NULL;
    ...
}

MyClass * p = GetInstance();
Foo(*p);

أريد أن أؤكد مجددًا أن الطريقة الوحيدة للحصول على مرجع فارغ هي من خلال التعليمة البرمجية غير الصحيحة ، وبمجرد حصولك على سلوك غير محدد. من غير المنطقي أبدًا التحقق من وجود مرجع فارغ ؛ على سبيل المثال يمكنك محاولة if(&bar==NULL)... ولكن قد المحول البرمجي تحسين العبارة خارج الوجود! لا يمكن أبداً أن يكون المرجع الصالح خاليًا من وجهة نظر المترجم ، فالمقارنة دائمًا ما تكون خاطئة ، وهي حرة في التخلص من الجملة if رمزًا ميتًا - وهذا هو جوهر السلوك غير المعروف.

الطريقة المناسبة للبقاء بعيداً عن المشاكل هي تجنب dereferencing مؤشر NULL لإنشاء مرجع. إليك طريقة آلية لتحقيق ذلك.

template<typename T>
T& deref(T* p)
{
    if (p == NULL)
        throw std::invalid_argument(std::string("NULL reference"));
    return *p;
}

MyClass * p = GetInstance();
Foo(deref(p));

لإلقاء نظرة قديمة على هذه المشكلة من شخص لديه مهارات كتابية أفضل ، راجع Null References من Jim Hyslop و Herb Sutter.

للحصول على مثال آخر من مخاطر dereferencing مؤشر فارغ انظر Exposing سلوك غير محدد عند محاولة رمز المنفذ إلى نظام أساسي آخر بواسطة Raymond Chen.




I feel like there is yet another point that hasn't been covered here.

Unlike the pointers, references are syntactically equivalent to the object they refer to, ie any operation that can be applied to an object works for a reference, and with the exact same syntax (the exception is of course the initialization).

While this may appear superficial, I believe this property is crucial for a number of C++ features, for example:

  • Templates . Since template parameters are duck-typed, syntactic properties of a type is all that matters, so often the same template can be used with both T and T& .
    (or std::reference_wrapper<T> which still relies on an implicit cast to T& )
    Templates that cover both T& and T&& are even more common.

  • Lvalues . Consider the statement str[0] = 'X'; Without references it would only work for c-strings ( char* str ). Returning the character by reference allows user-defined classes to have the same notation.

  • Copy constructors . Syntactically it makes sense to pass objects to copy constructors, and not pointers to objects. But there is just no way for a copy constructor to take an object by value - it would result in a recursive call to the same copy constructor. This leaves references as the only option here.

  • Operator overloads . With references it is possible to introduce indirection to an operator call - say, operator+(const T& a, const T& b) while retaining the same infix notation. This also works for regular overloaded functions.

These points empower a considerable part of C++ and the standard library so this is quite a major property of references.




At the risk of adding to confusion, I want to throw in some input, I'm sure it mostly depends on how the compiler implements references, but in the case of gcc the idea that a reference can only point to a variable on the stack is not actually correct, take this for example:

#include <iostream>
int main(int argc, char** argv) {
    // Create a string on the heap
    std::string *str_ptr = new std::string("THIS IS A STRING");
    // Dereference the string on the heap, and assign it to the reference
    std::string &str_ref = *str_ptr;
    // Not even a compiler warning! At least with gcc
    // Now lets try to print it's value!
    std::cout << str_ref << std::endl;
    // It works! Now lets print and compare actual memory addresses
    std::cout << str_ptr << " : " << &str_ref << std::endl;
    // Exactly the same, now remember to free the memory on the heap
    delete str_ptr;
}

Which outputs this:

THIS IS A STRING
0xbb2070 : 0xbb2070

If you notice even the memory addresses are exactly the same, meaning the reference is successfully pointing to a variable on the heap! Now if you really want to get freaky, this also works:

int main(int argc, char** argv) {
    // In the actual new declaration let immediately de-reference and assign it to the reference
    std::string &str_ref = *(new std::string("THIS IS A STRING"));
    // Once again, it works! (at least in gcc)
    std::cout << str_ref;
    // Once again it prints fine, however we have no pointer to the heap allocation, right? So how do we free the space we just ignorantly created?
    delete &str_ref;
    /*And, it works, because we are taking the memory address that the reference is
    storing, and deleting it, which is all a pointer is doing, just we have to specify
    the address with '&' whereas a pointer does that implicitly, this is sort of like
    calling delete &(*str_ptr); (which also compiles and runs fine).*/
}

Which outputs this:

THIS IS A STRING

Therefore a reference IS a pointer under the hood, they both are just storing a memory address, where the address is pointing to is irrelevant, what do you think would happen if I called std::cout << str_ref; AFTER calling delete &str_ref? Well, obviously it compiles fine, but causes a segmentation fault at runtime because it's no longer pointing at a valid variable, we essentially have a broken reference that still exists (until it falls out of scope), but is useless.

In other words, a reference is nothing but a pointer that has the pointer mechanics abstracted away, making it safer and easier to use (no accidental pointer math, no mixing up '.' and '->', etc.), assuming you don't try any nonsense like my examples above ;)

Now regardless of how a compiler handles references, it will always have some kind of pointer under the hood, because a reference must refer to a specific variable at a specific memory address for it to work as expected, there is no getting around this (hence the term 'reference').

The only major rule that's important to remember with references is that they must be defined at the time of declaration (with the exception of a reference in a header, in that case it must be defined in the constructor, after the object it's contained in is constructed it's too late to define it).

Remember, my examples above are just that, examples demonstrating what a reference is, you would never want to use a reference in those ways! For proper usage of a reference there are plenty of answers on here already that hit the nail on the head




It doesn't matter how much space it takes up since you can't actually see any side effect (without executing code) of whatever space it would take up.

On the other hand, one major difference between references and pointers is that temporaries assigned to const references live until the const reference goes out of scope.

فمثلا:

class scope_test
{
public:
    ~scope_test() { printf("scope_test done!\n"); }
};

...

{
    const scope_test &test= scope_test();
    printf("in scope\n");
}

سوف تطبع:

in scope
scope_test done!

This is the language mechanism that allows ScopeGuard to work.




المراجع تشبه إلى حد كبير المؤشرات ، ولكنها مصممة خصيصًا لتكون مفيدة لتحسين استخدام برامج التحويل البرمجي.

  • تم تصميم المراجع بحيث يسهل على المترجم أن يقيس أي الأسماء المستعارة المرجعية التي هي المتغيرات. هناك ميزتان رئيسيتان مهمتان للغاية: لا "حساب مرجعي" ولا إعادة تعيين للمراجع. هذه تسمح للالمترجم لمعرفة أي المراجع الاسم المستعار المتغيرات في وقت التحويل البرمجي.
  • يُسمح للمراجع بالرجوع إلى المتغيرات التي لا تحتوي على عناوين ذاكرة ، مثل تلك التي يختار المحول البرمجي وضعها في السجلات. إذا كنت تأخذ عنوان متغير محلي ، فمن الصعب جدًا على المترجم وضعه في سجل.

كمثال:

void maybeModify(int& x); // may modify x in some way

void hurtTheCompilersOptimizer(short size, int array[])
{
    // This function is designed to do something particularly troublesome
    // for optimizers. It will constantly call maybeModify on array[0] while
    // adding array[1] to array[2]..array[size-1]. There's no real reason to
    // do this, other than to demonstrate the power of references.
    for (int i = 2; i < (int)size; i++) {
        maybeModify(array[0]);
        array[i] += array[1];
    }
}

قد يدرك المترجم المحسن أننا نصل إلى [0] و [1] مجموعة كبيرة. إنه يحب تحسين الخوارزمية من أجل:

void hurtTheCompilersOptimizer(short size, int array[])
{
    // Do the same thing as above, but instead of accessing array[1]
    // all the time, access it once and store the result in a register,
    // which is much faster to do arithmetic with.
    register int a0 = a[0];
    register int a1 = a[1]; // access a[1] once
    for (int i = 2; i < (int)size; i++) {
        maybeModify(a0); // Give maybeModify a reference to a register
        array[i] += a1;  // Use the saved register value over and over
    }
    a[0] = a0; // Store the modified a[0] back into the array
}

لجعل هذا التحسين ، يحتاج إلى إثبات أن لا شيء يمكن أن يغير الصفيف [1] أثناء المكالمة. هذا من السهل القيام به. أنا لا أقل أبدًا من 2 ، لذا لا يمكن للمصفوفة [i] الإشارة أبداً إلى الصفيف [1]. maybeModify () يتم إعطاء a0 كمرجع (صفيف مستعار [0]). نظرًا لعدم وجود حساب "مرجع" ، يجب على المترجم أن يثبت فقط أن mayModify لن يحصل على عنوان x ، وقد أثبت أنه لا شيء يتغير الصفيف [1].

كما يجب أن يثبت أنه لا توجد طرق يمكن للمكالمة المستقبلية قراءة / كتابة [0] بينما يكون لدينا نسخة تسجيل مؤقتة في a0. غالبًا ما يكون هذا أمرًا ضئيلًا لإثباته ، لأنه من الواضح في العديد من الحالات أن المرجع لا يتم تخزينه أبدًا في بنية دائمة مثل مثيل فئة.

الآن افعل نفس الشيء مع المؤشرات

void maybeModify(int* x); // May modify x in some way

void hurtTheCompilersOptimizer(short size, int array[])
{
    // Same operation, only now with pointers, making the
    // optimization trickier.
    for (int i = 2; i < (int)size; i++) {
        maybeModify(&(array[0]));
        array[i] += array[1];
    }
}

السلوك هو نفسه. الآن فقط من الأصعب بكثير إثبات أن mayModify لا يقوم بتعديل المصفوفة [1] ، لأننا بالفعل أعطيناها مؤشرًا ؛ القطة خارج الحقيبة. الآن عليها أن تفعل البرهان الأكثر صعوبة: تحليل ثابت ل mayModify لإثبات أنه لم يكتب إلى & x + 1. كما يجب أن يثبت أنه لا ينقذ مؤشر يمكن أن يشير إلى صفيف [0] ، وهو فقط كما صعبة.

إن المترجمين الحديثين يصبحون أفضل وأفضل في التحليل الساكن ، لكن من الجيد دائماً مساعدتهم واستخدام المراجع.

وبطبيعة الحال ، في حالة عدم وجود مثل هذه التحسينات الذكية ، سيحول المجمعون بالفعل المراجع إلى مؤشرات عند الحاجة.




I have an analogy for references and pointers, think of references as another name for an object and pointers as the address of an object.

// receives an alias of an int, an address of an int and an int value
public void my_function(int& a,int* b,int c){
    int d = 1; // declares an integer named d
    int &e = d; // declares that e is an alias of d
    // using either d or e will yield the same result as d and e name the same object
    int *f = e; // invalid, you are trying to place an object in an address
    // imagine writting your name in an address field 
    int *g = f; // writes an address to an address
    g = &d; // &d means get me the address of the object named d you could also
    // use &e as it is an alias of d and write it on g, which is an address so it's ok
}



في حين يتم استخدام كل من المراجع والمؤشرات للوصول بشكل غير مباشر إلى قيمة أخرى ، هناك اختلافان مهمان بين المراجع والمؤشرات. الأول هو أن المرجع يشير دائمًا إلى كائن: إنه خطأ في تحديد مرجع بدون تهيئة له. سلوك التخصيص هو الاختلاف المهم الثاني: يؤدي التخصيص إلى مرجع إلى تغيير الكائن المرتبط به المرجع ؛ فإنه لا rebind المرجع إلى كائن آخر. وبمجرد التهيئة ، يشير المرجع دائمًا إلى نفس الكائن الأساسي.

خذ بعين الاعتبار هاتين الشظايا البرنامج. في الأول ، نخصص مؤشرًا لآخر:

int ival = 1024, ival2 = 2048;
int *pi = &ival, *pi2 = &ival2;
pi = pi2;    // pi now points to ival2

بعد المهمة ، ival ، يبقى الكائن الذي تم تناوله بواسطة pi بدون تغيير. The assignment changes the value of pi, making it point to a different object. Now consider a similar program that assigns two references:

int &ri = ival, &ri2 = ival2;
ri = ri2;    // assigns ival2 to ival

This assignment changes ival, the value referenced by ri, and not the reference itself. After the assignment, the two references still refer to their original objects, and the value of those objects is now the same as well.




A reference to a pointer is possible in C++, but the reverse is not possible means a pointer to a reference isn't possible. A reference to a pointer provides a cleaner syntax to modify the pointer. Look at this example:

#include<iostream>
using namespace std;

void swap(char * &str1, char * &str2)
{
  char *temp = str1;
  str1 = str2;
  str2 = temp;
}

int main()
{
  char *str1 = "Hi";
  char *str2 = "Hello";
  swap(str1, str2);
  cout<<"str1 is "<<str1<<endl;
  cout<<"str2 is "<<str2<<endl;
  return 0;
}

And consider the C version of the above program. In C you have to use pointer to pointer (multiple indirection), and it leads to confusion and the program may look complicated.

#include<stdio.h>
/* Swaps strings by swapping pointers */
void swap1(char **str1_ptr, char **str2_ptr)
{
  char *temp = *str1_ptr;
  *str1_ptr = *str2_ptr;
  *str2_ptr = temp;
}

int main()
{
  char *str1 = "Hi";
  char *str2 = "Hello";
  swap1(&str1, &str2);
  printf("str1 is %s, str2 is %s", str1, str2);
  return 0;
}

Visit the following for more information about reference to pointer:

As I said, a pointer to a reference isn't possible. Try the following program:

#include <iostream>
using namespace std;

int main()
{
   int x = 10;
   int *ptr = &x;
   int &*ptr1 = ptr;
}



Both references and pointers can be used to change local variables of one function inside another function. Both of them can also be used to save copying of big objects when passed as arguments to functions or returned from functions, to get efficiency gain. Despite above similarities, there are following differences between references and pointers.

References are less powerful than pointers

1) بمجرد إنشاء مرجع ، لا يمكن جعله لاحقًا مرجعًا إلى كائن آخر ؛ لا يمكن أن تكون متقلبة. غالبا ما يتم ذلك مع مؤشرات.

2) لا يمكن أن تكون المراجع فارغة. غالباً ما يتم وضع المؤشرات NULL للإشارة إلى أنها لا تشير إلى أي شيء صالح.

3) يجب أن تتم تهيئة المرجع عند الإعلان عنه. لا يوجد مثل هذا القيد مع مؤشرات

Due to the above limitations, references in C++ cannot be used for implementing data structures like Linked List, Tree, etc. In Java, references don't have above restrictions, and can be used to implement all data structures. References being more powerful in Java, is the main reason Java doesn't need pointers.

تعد المراجع أكثر أمانًا وأسهل في الاستخدام:

1) أكثر أمانًا: بما أنه يجب تهيئة المراجع ، فمن غير المحتمل وجود إشارات برية مثل المؤشرات البرية. لا يزال من الممكن وجود مراجع لا تشير إلى موقع صالح

2) سهولة الاستخدام: لا تحتاج المراجع إلى مشغل إلغاء الإشارة لإمكانية الوصول إلى القيمة. يمكن استخدامها مثل المتغيرات العادية. مطلوب "&" المشغل فقط في وقت الإعلان. كما يمكن الوصول إلى أعضاء مرجع الكائن باستخدام عامل نقطة (".") ، بخلاف المؤشرات التي تحتاج إلى مشغل السهم (->) للوصول إلى الأعضاء.

Together with the above reasons, there are few places like copy constructor argument where pointer cannot be used. Reference must be used pass the argument in copy constructor. Similarly references must be used for overloading some operators like ++ .




Another difference is that you can have pointers to a void type (and it means pointer to anything) but references to void are forbidden.

int a;
void * p = &a; // ok
void & p = a;  //  forbidden

I can't say I'm really happy with this particular difference. I would much prefer it would be allowed with the meaning reference to anything with an address and otherwise the same behavior for references. It would allow to define some equivalents of C library functions like memcpy using references.




بصرف النظر عن السكر النحوي ، مرجع هو مؤشر const ( لا مؤشر إلى const ). يجب عليك تحديد ما تشير إليه عندما تعلن متغير المرجع ، ولا يمكنك تغييره لاحقًا.

تحديث: الآن بعد أن فكرت في الأمر أكثر من ذلك ، هناك فرق مهم.

يمكن استبدال هدف مؤشر const بأخذ عنوانه واستخدام قالب Const.

لا يمكن استبدال هدف المرجع بأي شكل من الأشكال بأقل من UB.

يجب أن يسمح هذا المحول للقيام المزيد من التحسين على مرجع.




Links