سؤال

(سألت الاختلاف في هذه المسألة على شركات.الأمراض المنقولة جنسيا.c++ ولكن لم تحصل على إجابة.)

لماذا الدعوة إلى f(arg) في هذه التعليمة البرمجية استدعاء const المرجع الزائد f?

void f(const std::string &); //less efficient
void f(std::string &&); //more efficient

void g(const char * arg)
{
     f(arg);
}

حدسي يقول أن f(string &&) الزائد يجب أن يتم اختياره ، لأن arg تحتاج إلى تحويلها إلى مؤقت مهما مؤقتة مباريات rvalue مرجع أفضل من lvalue المرجعية.

هذا ليس ما يحدث في دول مجلس التعاون الخليجي ، MSVC (تحرير:شكرا سومانت:هذا لا يحدث في دول مجلس التعاون الخليجي 4.3-4.5).على الأقل G++ و MSVC أي lvalue لا ربط rvalue الإشارة الحجة ، حتى إذا هناك وسيطة المؤقتة التي تم إنشاؤها.في الواقع ، إذا كان const المرجع الزائد ليس الوقت الحاضر ، المجمعين تشخيص خطأ.ومع ذلك, الكتابة f(arg + 0) أو f(std::string(arg)) لا اختيار rvalue إشارة الزائد كما كنت تتوقع.

من قراءتي C++0x القياسية, يبدو التحويل الضمني من const char * إلى سلسلة ينبغي أخذها في الاعتبار عند النظر إذا f(string &&) صالحة فقط عند تمرير const lvalue المرجع الحجج.القسم 13.3 (الزائد القرار) لا يفرق بين rvalue الحكام و const المراجع في كثير من الأماكن.أيضا, يبدو أن القاعدة التي تمنع lvalues من ملزمة rvalue المراجع (13.3.3.1.4/3) لا ينطبق إذا كان هناك وسيط مؤقت - بعد كل شيء, انها آمنة تماما في الانتقال من المؤقت.

هو هذا:

  1. لي قراءة خاطئة/تسيئوا القياسية ، حيث نفذت السلوك المستهدف السلوك و هناك سبب وجيه لماذا بلدي على سبيل المثال يجب أن تتصرف بالطريقة التي يفعل ؟
  2. خطأ المحول البرمجي البائعين بطريقة أو بأخرى ؟ أو خطأ يقوم على تنفيذ استراتيجيات ؟ أو خطأ في مثلدول مجلس التعاون الخليجي (من أين هذا lvalue/rvalue مرجعية ملزمة القاعدة الأولى تنفيذها) ، التي تم نسخها من قبل البائعين ؟
  3. خلل في معيار أو غير مقصودة ، أو شيء ينبغي توضيحها ؟

تحرير:يجب متابعة مسألة ذات صلة: C++0x rvalue المراجع - lvalues-rvalue ملزمة

هل كانت مفيدة؟

المحلول

دول مجلس التعاون الخليجي تقوم به من الخطأ وفقا FCD.FCD يقول في 8.5.3 عن مرجعية ملزمة

  • إذا كان المرجع هو lvalue المرجعية مهيئ التعبير [lvalue / نوع فئة] ...
  • وإلا فإن الإشارة يجب أن يكون lvalue إشارة إلى غير متطايرة const نوع (أي cv1 يكون const) أو الإشارة يكون rvalue المرجعية مهيئ التعبير يكون rvalue أو يكون نوع وظيفة.

قضيتك من أجل الدعوة إلى std::string && مباريات أيا منهم ، لأن مهيئ هو lvalue.أنها لا تحصل على مكان إنشاء مؤقت rvalue لأن هذا toplevel رصاصة بالفعل يتطلب rvalue.

الآن الزائد القرار لا تستخدم مباشرة مرجعية ملزمة لمعرفة ما إذا كان هناك وجود ضمني تحويل تسلسل.وبدلا من ذلك يقول في 13.3.3.1.4/2

عندما معلمة من نوع مرجع لا بد مباشرة إلى حجة التعبير تحويل تسلسل هو المطلوب لتحويل الحجة التعبير الكامنة نوع من الإشارة وفقا 13.3.3.1.

وهكذا الزائد القرار الأرقام الفائز ، على الرغم من أن الفائز في الواقع قد لا تكون قادرة على ربط هذه الحجة.على سبيل المثال:

struct B { B(int) { /* ... */ } };
struct A { int bits: 1; };

void f(int&);
void f(B);
int main() { A a; f(a.bits); }

مرجعية ملزمة في 8.5 يحظر bitfields لربط lvalue المراجع.ولكن الزائد القرار يقول أن تحويل تسلسل هو تحويل int, وبالتالي النجاح على الرغم عندما يتم إجراء المكالمة في وقت لاحق ، والدعوة سوء تشكيلها.وهكذا bitfields سبيل المثال هو سوء تشكيلها.إذا كان اختيار B الإصدار ، فإنه قد نجحت ، ولكن هناك حاجة إلى تعريف المستخدم التحويل.

ومع ذلك, هناك اثنين من الاستثناءات لهذه القاعدة.هذه هي

باستثناء ضمني معلمة الكائن الذي يرى 13.3.1 القياسية تحويل تسلسل لا يمكن أن تتحقق إذا كان يتطلب ملزم وهو lvalue الإشارة إلى غير const إلى rvalue أو ملزمة أحد rvalue إشارة إلى lvalue.

وهكذا المكالمة التالية صحيحة:

struct B { B(int) { /* ... */ } };
struct A { int bits: 1; };

void f(int&); /* binding an lvalue ref to non-const to rvalue! */
void f(B);
int main() { A a; f(1); }

وهكذا ، على سبيل المثال المكالمات const T& الإصدار

void f(const std::string &);
void f(std::string &&); // would bind to lvalue!

void g(const char * arg) { f(arg); }

ومع ذلك ، إذا كنت أقول f(arg + 0), ، يمكنك إنشاء rvalue ، وبالتالي فإن الوظيفة الثانية هي قابلة للحياة.

نصائح أخرى

كان خلل في معيار مشروع تقرأ.هذا عيب في كأثر جانبي لبعض حريصة التحرير إلى عدم السماح ملزمة rvalue إشارات إلى lvalues لأسباب تتعلق بالسلامة.

الحدس الخاص بك هو الصحيح.بالطبع ليس هناك أي ضرر في السماح rvalue إشارة إلى الرجوع إلى بعض لم يذكر اسمه مؤقت حتى لو كان مهيئ كان lvalue التعبير.بعد كل شيء, هذا هو ما rvalue المراجع هي.مسألة لاحظتم تم إصلاح في العام الماضي.القادمة معيار الولاية الثانية الزائد سوف تكون التقطت في المثال الخاص بك حيث rvalue المرجعية سوف أشير إلى بعض المؤقتة كائن string.

حكم إصلاح في مشروع n3225.pdf (2010-11-27):

  • [...]
  • وإلا فإن الإشارة يجب أن يكون lvalue إشارة إلى غير متطايرة const نوع (أي cv1 يكون const) أو الإشارة يكون rvalue المرجعية و مهيئ التعبير يكون rvalue أو وظيفة نوع. [...]
    • [...]
    • وإلا مؤقت من [...] خلق [...]
        double&& rrd3 = i; // rrd3 refers to temporary with value 2.0

ولكن N3225 يبدو أنه قد فاتني أن أقول ما i في هذا المثال.أحدث مشروع N3290 يحتوي على هذه الأمثلة:

        double d2 = 1.0;
        double&& rrd2 = d2; // error: copying lvalue of related type
        int i3 = 2;
        double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0

منذ MSVC نسخة تم إصدارها من قبل هذه المشكلة حصلت ثابتة, فإنه لا يزال يعالج rvalue المراجع وفقا للقواعد القديمة.التالي MSVC الإصدار المتوقع لتنفيذ جديدة rvalue الإشارة القواعد (يطلق عليها اسم "rvalue المراجع 2.1" من قبل MSVC المطورين) انظر الرابط.

لم أكن أرى السلوك المذكورة من قبل دوغ على g++.g++ 4.5 و 4.4.3 كل مكالمة f(string &&) كما هو متوقع ولكن VS2010 المكالمات f(const string &).التي g++ الإصدار الذي تستخدمه ؟

الكثير من الأشياء في المشروع الحالي من مستوى تحتاج إلى توضيح, إذا كنت تسألني.و المجمعين لا تزال النامية ، لذلك فمن الصعب أن تثق مساعدتهم.

يبدو من الواضح جدا أن الحدس الخاص بك هو الصحيح... المؤقتات من أي نوع من المفترض أن ربط rvalue المراجع.على سبيل المثال ، §3.10 الجديد "التصنيف" القسم بشكل قاطع يحدد المؤقتات كما rvalues.

قد تكون المشكلة أن RR حجة مواصفات غير كاف في الاحتجاج إنشاء مؤقت.§5.2.2/5:"حيث المعلمة هي من const نوع مرجع كائن مؤقت هو عرض إذا لزم الأمر." هذا يبدو مثير للريبة الحصرية.

يبدو أن تنزلق من خلال الشقوق مرة أخرى في §13.3.3.1/6:(التشديد من الألغام)

عندما المعلمة نوع ليس مرجعا ، التحويل الضمني تسلسل نماذج نسخة تهيئة المعلمة من حجة التعبير.التحويل الضمني تسلسل هو المطلوب لتحويل الحجة التعبير إلى prvalue من نوع المعلمة.

علما بأن نسخة التهيئة string &&rr = "hello"; يعمل بشكل جيد في دول مجلس التعاون الخليجي.

تحرير: فعلا مشكلة لا وجود لها على نسختي من دول مجلس التعاون الخليجي.أنا لا تزال تحاول معرفة كيف المعيار الثاني تحويل المعرفة من قبل المستخدم تحويل تسلسل تتعلق تشكيل rvalue المرجعية.(هو RR تشكيل التحويل ؟ أو تمليها المنتشرة الحكايات مثل 5.2.2/5?)

نلقي نظرة على هذا:

http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx

rvalue المراجع:الزائد القرار

يبدو أن الحالة هو:"Lvalues يفضلون بقوة ملزمة lvalue المراجع".

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

إذا كنت تريد نقل دلالات استخدام f(std::move(arg)), أن تعمل مع كل من المجمعين.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top