سؤال

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

class object
{
    int get_value(int n) const
    {
        ...
    }

...


object x;

int a = x.get_value(1);
    ...
int b = x.get_value(1);

ثم يمكن للمترجم تحسين الاستدعاء الثاني وإما استخدام القيمة في السجل أو القيام بذلك ببساطة b = a;

هل هذا صحيح؟

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

المحلول

const يتعلق الأمر بدلالات البرنامج وليس بتفاصيل التنفيذ.يجب عليك وضع علامة على وظيفة العضو const عندما لا يغير الحالة المرئية للكائن، ويجب أن يكون قابلاً للاستدعاء على كائن هو نفسه const.ضمن أ const وظيفة العضو في الفصل X, ، نوع من this يكون X const *:المؤشر إلى ثابت X هدف.وبالتالي فإن جميع متغيرات الأعضاء فعالة const ضمن وظيفة العضو هذه (باستثناء mutable تلك).اذا كان لديك const الكائن، يمكنك الاتصال فقط const وظائف الأعضاء عليه.

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

class X
{
    int data;
    mutable boost::mutex m;
public:
    void set_data(int i)
    {
        boost::lock_guard<boost::mutex> lk(m);
        data=i;
    }
    int get_data() const // we want to be able to get the data on a const object
    {
        boost::lock_guard<boost::mutex> lk(m); // this requires m to be non-const
        return data;
    }
};

إذا كنت تحتفظ بالبيانات بواسطة المؤشر وليس بشكل مباشر (بما في ذلك المؤشرات الذكية مثل std::auto_ptr أو boost::shared_ptr) فيصبح المؤشر const في const وظيفة العضو، ولكن ليس البيانات المشار إليها، حتى تتمكن من تعديل البيانات المشار إليها.

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

الإصدار القادم من معيار C++ (C++0x) سيكون لها كلمة رئيسية جديدة constexpr.الوظائف الموسومة constexpr إرجاع قيمة ثابتة، بحيث يمكن تخزين النتائج مؤقتًا.هناك حدود لما يمكنك القيام به في مثل هذه الوظيفة (حتى يتمكن المترجم من التحقق من هذه الحقيقة).

نصائح أخرى

الكلمة الرئيسية متقلب على متغيرات الأعضاء يسمح لوظائف const بتغيير حالة الكائن في متناول اليد.

لا، فهو لا يقوم بتخزين البيانات مؤقتًا (على الأقل ليس كل المكالمات) نظرًا لأن الكود التالي عبارة عن دالة const صالحة تتغير بمرور الوقت:

int something() const { return m_pSomeObject->NextValue(); }

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

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

لا.

الطريقة const هي طريقة لا تغير حالة الكائن (أيحقولها)، ولكن لا يمكنك افتراض أنه في ضوء نفس المدخلات، يتم تحديد قيمة الإرجاع لطريقة const.بعبارة أخرى، const الكلمة الأساسية لا تعني أن الوظيفة فردية.على سبيل المثال، الطريقة التي تُرجع الوقت الحالي هي طريقة const ولكن قيمة الإرجاع الخاصة بها تتغير بين الاستدعاءات.

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

وفي هذا السياق قال أ const وظيفة العضو تعني ذلك this يتم التعامل معها على أنها أ const المؤشر أيضا.من الناحية العملية، فهذا يعني أنه لا يُسمح لك بتعديل حالة this داخل const وظيفة العضو.

بالنسبة للوظائف التي ليس لها أي آثار جانبية (أي ما تحاول تحقيقه)، فإن دول مجلس التعاون الخليجي لديها "سمة وظيفية" تسمى pure (تستخدمه بالقول __attribute__((pure))): http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

أشك في ذلك، لا يزال بإمكان الوظيفة استدعاء وظيفة عالمية غيرت حالة العالم ولا تنتهك الثوابت.

علاوة على حقيقة أن وظيفة العضو يمكنها تعديل البيانات العامة، فمن الممكن لوظيفة العضو تعديل الأعضاء القابلين للتغيير المعلنين بشكل صريح للكائن المعني.

كوري على صواب، ولكن ضع في اعتبارك أن أي متغيرات أعضاء تم وضع علامة عليها كـ متقلب يستطيع يمكن تعديلها في وظائف الأعضاء الثابتة.

ويعني أيضًا أنه يمكن استدعاء هذه الوظائف من وظائف const أخرى، أو عبر مراجع const أخرى.


يحرر:اللعنة، تم التغلب عليه بـ 9 ثواني.9!!!:)

يُسمح أيضًا لطرق const بتعديل السكان المحليين الثابتين.على سبيل المثال، ما يلي قانوني تمامًا (وسوف تؤدي الاستدعاءات المتكررة إلى bar() إلى إرجاع قيم متزايدة - وليس 0 مخبأة):

class Foo
{
public:
    int bar() const
    {
        static int x = 0;
        return x++;
    }
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top