क्या कॉन्स्ट्रेक्स का मतलब इनलाइन है?


105

निम्नलिखित इनलाइन फ़ंक्शन पर विचार करें:

// Inline specifier version
#include<iostream>
#include<cstdlib>

inline int f(const int x);

inline int f(const int x)
{
    return 2*x;
}

int main(int argc, char* argv[])
{
    return f(std::atoi(argv[1]));
}

और बाधा समतुल्य संस्करण:

// Constexpr specifier version
#include<iostream>
#include<cstdlib>

constexpr int f(const int x);

constexpr int f(const int x)
{
    return 2*x;
}

int main(int argc, char* argv[])
{
    return f(std::atoi(argv[1]));
}

मेरा प्रश्न यह है कि क्या constexprनिर्दिष्टकर्ता इस अर्थ में inlineविनिर्देशक का अर्थ करता है कि यदि किसी constexprफ़ंक्शन को एक गैर-स्थिर तर्क दिया जाता है , तो कंपाइलर फ़ंक्शन की कोशिश करेगा inlineजैसे कि inlineविनिर्देशक को अपनी घोषणा में रखा गया था?

क्या C ++ 11 मानक इसकी गारंटी देता है?


5
'[विल] कंपाइलर फंक्शन को इनलाइन करने की कोशिश करता है' ऐसा नहीं है जो inlineस्पेसियर करता है। (या हो सकता है कि मैंने आपकी बात को गलत समझा हो।)
ल्यूक डैंटन

5
inlineविनिर्देशक नहीं रह गया है के साथ कुछ भी नहीं है इनलाइनिंग
कश्मीर ballo

2
प्रश्न गलत धारणा पर पैर रखता है जो inlineसीधे इनलाइनिंग से संबंधित है। तो नहीं, constexprविनिर्देशक inlineउस अर्थ में निर्दिष्ट नहीं करता है, क्योंकि यह अर्थ मौजूद नहीं है।
क्रिश्चियन राऊ

जवाबों:


139

हां ([dcl.constexpr], C ++ 11 मानक में .57.1.5 / 2): "कॉन्स्ट्रेक्स फ़ंक्शंस और कॉन्सटेक्प कन्स्ट्रक्टर्स निहित रूप से इनलाइन (7.1.2) हैं।"

ध्यान दें, हालांकि, inlineनिर्दिष्टकर्ता का वास्तव में बहुत कम (यदि कोई है) इस बात पर प्रभाव पड़ता है कि क्या संकलक फ़ंक्शन इनलाइन का विस्तार करने की संभावना है या नहीं। हालांकि, यह एक परिभाषा नियम को प्रभावित करता है, और उस दृष्टिकोण से, constexprफ़ंक्शन के लिए फ़ंक्शन के समान नियमों का पालन करने के लिए कंपाइलर की आवश्यकता होती है inline

मैं भी की परवाह किए बिना कि जोड़ना चाहिए constexprजिसका अर्थ है inline, के लिए नियमों को constexprसी ++ 11 में कार्यों के लिए उन्हें आवश्यक सरल पर्याप्त होना करने के लिए है कि वे अक्सर इनलाइन विस्तार (प्राथमिक अपवाद उन है कि पुनरावर्ती हैं किया जा रहा है) के लिए बेहतर साबित थे। तब से, हालांकि, नियमों ने उत्तरोत्तर शिथिलता प्राप्त की है, इसलिए constexprइसे बड़े पैमाने पर, अधिक जटिल कार्यों के लिए लागू किया जा सकता है।


यह देखते हुए कि विचार यह है कि निरंतर अभिव्यक्तियों का संकलन समय पर किया जाता है, मुझे लगता है कि constexprकार्यों के अधिकांश उपयोग किसी भी कोड पीढ़ी का कारण नहीं
बनेंगे

11
@KerrekSB constexprफ़ंक्शन का संकलन समय पर संभावित रूप से मूल्यांकन किया जाता है। हालाँकि, C ++ 14 मानक लोगों के साथ अटे पड़े हैं, जो कि रनटाइम के समय कहलाएंगे। उदाहरण के लिए:std::array<T,N>::at
एप्लाइड

@ ईपनामे हाँ लेकिन केवल सबसे कम रूप में हालांकि opcodes के रूप में रहेगा। उदाहरण: बाउंड चेक, का निर्माण समय पर किया जाएगा, क्योंकि उनका कोड पथ कांस्टेबल है। लेकिन लौटाया गया मान * (डेटा + ऑफसेट)
v.oddou

16

constexprinlineगैर-स्थैतिक चर के लिए मतलब नहीं है (C ++ 17 इनलाइन चर)

जबकि कार्यों के लिए constexprइसका मतलब inlineहै, यह गैर-स्थिर चर के लिए उस प्रभाव नहीं है, C ++ 17 इनलाइन चर पर विचार।

उदाहरण के लिए, यदि आप मेरे द्वारा पोस्ट किया गया न्यूनतम उदाहरण लेते हैं: इनलाइन चर कैसे काम करते हैं? और inlineबस को छोड़ दें constexpr, तो चर को कई पते मिलते हैं, जो इनलाइन चर से बचते हैं।

constexpr स्थैतिक चर हालांकि स्पष्ट रूप से स्थिर होते हैं।

मिनिमल उदाहरण है कि constexprतात्पर्य inlineकार्यों के लिए

जैसा कि बताया गया है: https://stackoverflow.com/a/14391320/895245 का मुख्य प्रभाव inlineइनलाइन पर नहीं है, लेकिन किसी फ़ंक्शन की कई परिभाषाओं की अनुमति देने के लिए, मानक उद्धरण इस पर: C ++ शीर्षलेख फ़ाइल में कार्यान्वयन कैसे शामिल हो सकता है?

हम निम्नलिखित उदाहरण के साथ खेलकर देख सकते हैं:

main.cpp

#include <cassert>

#include "notmain.hpp"

int main() {
    assert(shared_func() == notmain_func());
}

notmain.hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

inline int shared_func() { return 42; }
int notmain_func();

#endif

notmain.cpp

#include "notmain.hpp"

int notmain_func() {
    return shared_func();
}

संकलित करें और चलाएं:

g++ -c -ggdb3  -O0 -Wall -Wextra -std=c++11 -pedantic-errors  -o 'notmain.o' 'notmain.cpp' 
g++ -c -ggdb3  -O0 -Wall -Wextra -std=c++11 -pedantic-errors  -o 'main.o' 'main.cpp' 
g++ -ggdb3  -O0 -Wall -Wextra -std=c++11 -pedantic-errors  -o 'main.out' notmain.o main.o
./main.out

यदि हम हटाते inlineहैं shared_func, तो लिंक के साथ विफल होगा:

multiple definition of `shared_func()'

क्योंकि हेडर कई .cppफाइलों में शामिल हो जाता है ।

लेकिन अगर हम inlineसाथ बदलते हैं constexpr, तो यह फिर से काम करता है, क्योंकि constexprइसका मतलब भी है inline

जीसीसी लागू करता है कि प्रतीकों को ईएलएफ ऑब्जेक्ट फाइलों पर कमजोर के रूप में चिह्नित करके: सी ++ हेडर फ़ाइल को कैसे लागू किया जा सकता है?

जीसीसी 8.3.0 में परीक्षण किया गया।


3
BTW, एक स्थिर वर्ग सदस्य चर घोषित constexprअभी भी इनलाइन है। cppreference.com : एक स्थिर सदस्य चर (लेकिन नाम स्थान-स्कोप वैरिएबल) घोषित नहीं किया गया constexprहै, यह एक इनलाइन वैरिएबल है।
anton_rh

@anton_rh धन्यवाद, मैंने वह नियम, अद्यतन उत्तर नहीं देखा था।
सिरो सेंटिल्ली 郝海东 冠状 iro i '' 19

यह ऐसा नहीं है जो खुले-std.org/JTC1/SC22/WG21/docs/papers/2016/p0386r0.pdf कहता है। यह कहता है कि कॉन्स्टेक्सप्रॉप का मतलब चर के लिए इनलाइन है। वर्ग गुंजाइश के नाम स्थान के बीच अंतर का कोई उल्लेख नहीं है।
v.oddou
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.