Const olmayan bir başvuru nasıl geçici bir nesneye bağlanamaz?


226

Geçici bir nesneye neden olmayan const referansı almasına izin verilmiyor, hangi işlev getx()döndürüyor? Açıkçası, bu C ++ Standardı tarafından yasaklanmıştır, ancak standardın bir referansı değil , bu kısıtlamanın amacı ile ilgileniyorum .

struct X
{
    X& ref() { return *this; }
};

X getx() { return X();}

void g(X & x) {}    

int f()
{
    const X& x = getx(); // OK
    X& x = getx(); // error
    X& x = getx().ref(); // OK
    g(getx()); //error
    g(getx().ref()); //OK
    return 0;
}
  1. Bir nesneye sürekli başvuru C ++ Standardı tarafından yasaklanmadığından , nesnenin kullanım ömrünün neden olamayacağı açıktır .
  2. Geçici nesnenin yukarıdaki örnekte sabit olmadığı açıktır, çünkü sabit olmayan fonksiyonlara çağrılara izin verilir. Örneğin ref(), geçici nesneyi değiştirebilir.
  3. Ayrıca ref(), derleyiciyi kandırmanıza ve bu geçici nesneye bir bağlantı almanıza izin verir ve bu da sorunumuzu çözer.

Ek olarak:

"Sabit referansa geçici bir nesne atamak bu nesnenin ömrünü uzatır" ve "Sabit olmayan referanslar hakkında hiçbir şey söylenmez" derler. Benim ek sorum . Aşağıdaki atama geçici nesnenin ömrünü uzatır mı?

X& x = getx().ref(); // OK

4
Ben sadece standartta belirtildiği için, const referansına geçici bir nesne atamanın bu nesnenin ömrünü const referansının ömrünü uzattığına "nesnenin ömrü neden olamaz" kısmına katılmıyorum. Const olmayan referanslar hakkında hiçbir şey söylenmiyor ...
SadSido

3
Peki, bunun sebebi ne "Const olmayan referanslar hakkında hiçbir şey söylenmez ...". Sorumun bir parçası. Bunda bir sence var mı? Standardın yazarları, const olmayan referansları unutmuş olabilir ve yakında bir sonraki Temel Sorunu göreceğiz?
Alexey Malistov


4
@Michael: VC, değerleri sabit olmayan referanslara bağlar. Buna bir özellik diyorlar, ama gerçekten bir hata. (Bunun bir hata olmadığını, çünkü doğal olarak mantıksız olduğunu, ancak açıkça saçma hataları önlemek için
dışlandığını unutmayın

Yanıtlar:


97

Rvalue referansları hakkında bu Visual C ++ blog makalesinden :

... C ++ geçici olarak geçişleri değiştirmenizi istemez, ancak değiştirilebilir bir değer üzerinde sabit olmayan bir üye işlevini doğrudan çağırmak açıktır, bu nedenle izin verilir ...

Temel olarak, geçici nesneler oldukları ve herhangi bir an ölecekleri için geçici olarak değiştirmeye çalışmamalısınız. Const olmayan yöntemleri çağırmanıza izin verilmesinin nedeni, ne yaptığınızı bildiğiniz ve bu konuda açık olduğunuz sürece (örneğin, reinterpret_cast kullanarak) bazı "aptal" şeyler yapmaya açık olmanızdır. Ancak, geçici olmayan bir referansa geçici olarak bağlanırsanız, nesneyi manipülasyonunuzun kaybolması için onu "sonsuza dek" geçirmeye devam edebilirsiniz, çünkü tamamen unutmuş olduğunuz bir yerde bu bir geçiciydi.

Ben olsaydım, işlevlerimin tasarımını yeniden düşünürdüm. Neden g () referansı kabul ediyor, parametreyi değiştiriyor mu? Hayır ise, bunu const referans yapın, eğer evet ise, neden geçici olarak geçmeye çalışıyorsunuz, değiştirdiğiniz bir geçici olduğunu umursamıyor musunuz? Neden getx () geçici olarak geri dönüyor? Gerçek senaryonuzu ve neyi başarmaya çalıştığınızı bizimle paylaşırsanız, bunu nasıl yapacağınıza dair bazı iyi öneriler alabilirsiniz.

Dile karşı çıkmak ve derleyiciyi kandırmak nadiren problemleri çözer - genellikle problem yaratır.


Edit: Yorum soruları adresleme: 1) X& x = getx().ref(); // OK when will x die?- Bilmiyorum ve umurumda değil, çünkü bu tam olarak "dile karşı" ile kastediyorum. Dil, "geçici referanslar, const referansına bağlı olmadıkça, ifadenin sonunda ölür, bu durumda referans kapsam dışına çıktığında ölür" der. Bu kuralı uyguladığınızda, x, bir sonraki ifadenin başında zaten ölü gibi görünüyor, çünkü const referansına bağlı değil (derleyici ref () 'nin ne döndürdüğünü bilmiyor). Ancak bu sadece bir tahmindir.

2) Amacımı açıkça belirtmiştim: sadece anlam ifade etmediği için geçici değişiklikleri değiştirmenize izin verilmiyor (C ++ 0x rvalue referanslarını göz ardı ederek). "Öyleyse neden const üyesi olmayan üyeleri aramama izin veriliyor?" iyi bir yanıt, ancak yukarıda belirttiğimden daha iyi bir cevabım yok.

3) X& x = getx().ref();Açıklamanın sonunda ölmek konusunda x konusunda haklıysam , problemler açıktır.

Her neyse, sorunuza ve yorumlarınıza dayanarak bu ekstra cevapların bile sizi tatmin edeceğini sanmıyorum. İşte son bir girişim / özet: C ++ komitesi, geçici değişiklikleri değiştirmenin mantıklı olmadığına karar verdi, bu nedenle sabit olmayan referanslara bağlanmaya izin vermediler. Bazı derleyici uygulamaları olabilir ya da tarihi konular da dahil, bilmiyorum. Daha sonra, bazı özel durumlar ortaya çıktı ve her şeye rağmen, hala const olmayan yöntemi çağırarak doğrudan modifikasyona izin vereceklerine karar verildi. Ancak bu bir istisnadır - genellikle geçişleri değiştirmenize izin verilmez. Evet, C ++ genellikle bu kadar garip.


2
@sbk: 1) Aslında, doğru ifade: "... tüm ifadenin sonunda ...". Bir "tam ifade", sanırım, başka bir ifadenin alt ifadesi olmayan olarak tanımlanır. Bu her zaman "ifadenin sonu" ile aynı olsun, emin değilim.
sbi

5
@sbk: 2) Aslında olan SağDeğerler (geçicileri) değiştirmesine izin. Bu tipler (yerleşik için yasak intvs.), ancak kullanıcı tanımlı türleri için izin verilir: (std::string("A")+"B").append("C").
sbi

6
@sbk: 3) Stroustrup'un (D&E'de), değerlerin sabit olmayan referanslara bağlanmasına izin vermemek için vermesinin nedeni, Alexey'in g()nesneyi değiştirmesi durumunda (sabit olmayan bir referans alan bir işlevden bekleyeceğiniz), ölecek bir nesneyi değiştirir, böylece hiç kimse değiştirilmiş değere ulaşamaz. Bunun büyük olasılıkla bir hata olduğunu söylüyor.
sbi

2
@sbk: Seni rahatsız ettiysem özür dilerim ama 2) nitpicking olduğunu düşünmüyorum. Değerler, bunları yapmadığınız sürece sabit değildir ve yerleşik olmadıkça bunları değiştirebilirsiniz. Örneğin dize örneğiyle yanlış bir şey yapıp yapmadığımı (JFTR: Yapmıyorum) anlamak biraz zaman aldı, bu yüzden bu ayrımı ciddiye almaya eğilimliyim.
sbi

5
Ben sbi ile aynı fikirdeyim - bu mesele hiç de çirkin değil . Sınıf tipi değerlerin en iyi şekilde sabit kalmaması hareket semantiğinin temelini oluşturur.
Johannes Schaub - litb

38

Kodunuzda getx()"rvalue" adı verilen geçici bir nesne döndürülür. Değerleri nesnelere (diğer bir deyişle değişkenler) kopyalayabilir veya sabit referanslara bağlayabilirsiniz (bu, ömürlerini referansın ömrünün sonuna kadar uzatacaktır). Değerleri sabit olmayan referanslara bağlayamazsınız.

Bu, kullanıcıların ifadenin sonunda ölecek bir nesneyi yanlışlıkla değiştirmesini önlemek için kasıtlı bir tasarım kararıdır:

g(getx()); // g() would modify an object without anyone being able to observe

Bunu yapmak istiyorsanız, önce yerel bir kopyasını veya nesneyi oluşturmanız veya bir const referansına bağlamanız gerekir:

X x1 = getx();
const X& x2 = getx(); // extend lifetime of temporary to lifetime of const reference

g(x1); // fine
g(x2); // can't bind a const reference to a non-const reference

Bir sonraki C ++ standardının değer referanslarını içereceğini unutmayın. Referans olarak bildiklerinize "lvalue referansları" denmektedir. Değerleri referans değerlerine bağlamanıza izin verilecek ve "değerlik" işlevlerini aşırı yükleyebilirsiniz:

void g(X&);   // #1, takes an ordinary (lvalue) reference
void g(X&&);  // #2, takes an rvalue reference

X x; 
g(x);      // calls #1
g(getx()); // calls #2
g(X());    // calls #2, too

Değer referanslarının arkasındaki fikir, bu nesneler yine de öleceğinden, bu bilgiden faydalanabileceğiniz ve belirli bir optimizasyon türü olan "semantiği taşıyın" denilen şeyi uygulayabileceğinizdir:

class X {
  X(X&& rhs)
    : pimpl( rhs.pimpl ) // steal rhs' data...
  {
    rhs.pimpl = NULL; // ...and leave it empty, but deconstructible
  }

  data* pimpl; // you would use a smart ptr, of course
};


X x(getx()); // x will steal the rvalue's data, leaving the temporary object empty

2
Merhaba, bu harika bir cevap. İhtiyaç bir şeyi bilmek, g(getx())does not iş onun imzası olduğu için g(X& x)ve get(x)bunu yapamıyoruz böylece bağlama geçici nesne (geçici nesnesi döndüren rvalue bir sabit olmayan referansa), doğru mu? Ve ilk kod const X& x2 = getx();const X& x1 = getx();
parçanızda

1
Bu hatayı yazdıktan 5 yıl sonra cevabımda belirttiğiniz için teşekkür ederim! :-/Evet, nedeniniz doğru olsa da, biraz geriye doğru olsa da: constGeçicileri (lvalue) olmayan referanslara bağlayamayız ve bu nedenle döndürülen getx()(ve değil get(x)) geçici , argüman olan lvalue referansına bağlanamaz g().
sbi

Umm, ne demek istedin getx()(değil get(x)) ?
SexyBeast

Ben yazarken "... GetX () (ve alamadım (x)) ..." , ben işlevin adıdır anlamına getx()değil, get(x)(yazdığın gibi).
sbi

Bu cevap terminolojiyi karıştırmaktadır. Değer, bir ifade kategorisidir. Geçici bir nesne bir nesnedir. Bir rvalue geçici bir nesneyi gösterebilir veya göstermeyebilir; ve geçici bir nesne bir değer ile gösterilebilir veya gösterilmeyebilir.
MM

16

Gösterdiğiniz, operatör zincirlemesine izin verildiğidir.

 X& x = getx().ref(); // OK

İfade 'getx (). Ref ();' ve bu 'x' a atanmadan önce tamamlanır.

Getx () yönteminin başvuruyu değil, tam olarak oluşturulmuş bir nesneyi yerel bağlama döndürdüğünü unutmayın. Nesne geçicidir, ancak sabit değildir , bu nedenle bir değeri hesaplamak veya başka yan etkilerin ortaya çıkması için diğer yöntemleri çağırmanıza izin verir.

// It would allow things like this.
getPipeline().procInstr(1).procInstr(2).procInstr(3);

// or more commonly
std::cout << getManiplator() << 5;

Bunun daha iyi bir örneği için bu cevabın sonuna bakın

Yapabilirsiniz değil bir referansa geçici bağlama böylece (düzensiz ve standart düzensiz gibi değil) bir sarkan referans ile bırakarak ifadenin sonuna imha edilecek bir nesneye bir başvuru üretecektir Bunu yaparken çünkü.

Ref () tarafından döndürülen değer geçerli bir referanstır, ancak yöntem döndürdüğü nesnenin ömrüne dikkat etmez (çünkü bu bilgiyi kendi bağlamı içinde tutamaz). Temel olarak şu eşdeğerleri yaptınız:

x& = const_cast<x&>(getX());

Bunu geçici bir nesneye sabit bir başvuru ile yapmanın uygun olmasının nedeni, standardın geçici ömrünü referansın ömrüne uzatmasıdır, böylece geçici nesnelerin ömrü ifadenin sonunun ötesine uzatılır.

Öyleyse geriye kalan tek soru, standardın neden nesnenin ömrünü ifadenin sonunun ötesine uzatması için geçicilere referans vermek istemediğidir?

Bunun derleyicinin geçici nesneler için doğru olmasını çok zorlaştıracağına inanıyorum. Bu, sınırlı kullanıma sahip olduğundan ve böylece yararlı bir şey yapmak için nesnenin bir kopyasını yapmaya zorladığı, ancak bazı sınırlı işlevsellik sağladığından geçici programlara const referansları için yapıldı.

Bu durumu düşünün:

int getI() { return 5;}
int x& = getI();

x++; // Note x is an alias to a variable. What variable are you updating.

Bu geçici nesnenin ömrünü uzatmak çok kafa karıştırıcı olacaktır.
Aşağıdaki sırada:

int const& y = getI();

Kullanmanın ve anlamanın sezgisel olduğu kodunu verecektir.

Değeri değiştirmek istiyorsanız, değeri bir değişkene döndürmeniz gerekir. Eğer obejct işlevinden geri kopyalama maliyetinden kaçınmaya çalışıyorsanız (nesne kopya geri inşa gibi görünüyor (teknik olarak)). Derleyicinin 'Dönüş Değeri Optimizasyonu'nda çok iyi olduğunu rahatsız etmeyin


3
"Öyleyse geriye kalan tek soru, standardın neden nesnenin ömrünü ifadenin sonunun ötesine uzatması için geçicilere referans vermek istemediğidir?" İşte bu! Sorumu anlıyorsun . Ama senin fikrine katılmıyorum. "Derleyiciyi çok zor yap" diyorsunuz ama const referansı için yapıldı. Örneğinizde "Not x, bir değişkenin diğer adıdır. Hangi değişkeni güncelleştiriyorsunuz?" Sorun değil. Benzersiz bir değişken vardır (geçici). Bazı geçici nesneler (5'e eşittir) değiştirilmelidir.
Alexey Malistov

@Martin: Sarkan referanslar sadece düzensiz değil. Yöntemde daha sonra erişildiğinde ciddi hatalara neden olabilirler!
mmmmmmmm

1
@Alexey: Bir const referansına bağlamanın bir geçici sürenin ömrünü artırdığı gerçeğinin kasıtlı olarak eklenen bir istisna olduğunu unutmayın (manuel optimizasyonlara izin vermek için TTBOMK). Const olmayan başvurular için bir istisna eklenmedi, çünkü const olmayan bir referansa geçici bir bağlamanın büyük olasılıkla bir programcı hatası olduğu görülmüştür.
sbi

1
@alexy: Görünmez bir değişkene başvuru! Bu sezgisel değil.
Martin York

const_cast<x&>(getX());mantıklı değil
curiousguy

10

Neden C ++ SSS'de ( cesur maden)tartışılıyor:

C ++ 'da, const olmayan başvurular değerlere bağlanabilir ve const başvuruları, değerlere veya değerlere bağlanabilir, ancak const olmayan bir değere bağlanabilecek hiçbir şey yoktur. Bu, insanları yeni değerlerinin kullanılabilmesi için yok edilen geçicilerin değerlerini değiştirmekten korumaktır . Örneğin:

void incr(int& a) { ++a; }
int i = 0;
incr(i);    // i becomes 1
incr(0);    // error: 0 is not an lvalue

Eğer bu artışa (0) ya hiç kimsenin görmeyeceğine geçici olarak izin verilirse ya da - çok daha kötüsü - 0 değeri 1 olur. 0 değerini tutmak için bir bellek yeri ayırın.


O Fortran "sıfır hata" tarafından ısırıldı programcı yüzünü görmek komik olurdu! x * 0 verir xmi? Ne? Ne??
John D

Bu son argüman özellikle zayıf. Bahsetmeye değer hiçbir derleyici aslında 0 değerini 1 olarak değiştirmez, hatta incr(0);böyle yorumlamaz . Açıkçası, buna izin verildiyse, geçici bir tamsayı oluşturma ve bunu şu incr()
değere

6

Ana konu şudur:

g(getx()); //error

mantıksal bir hatadır: gsonucunu değiştiriyor getx()ancak değiştirilen nesneyi inceleme şansınız yok. Eğer gbir lvalue referansı gerekli olmazdı daha sonra parametreyi değiştirmek gerek yoktu, değere veya const referans parametresi alabilirdi.

const X& x = getx(); // OK

geçerlidir çünkü bazen bir ifadenin sonucunu yeniden kullanmanız gerekir ve geçici bir nesneyle uğraştığınız oldukça açıktır.

Ancak bunu yapmak mümkün değil

X& x = getx(); // error

geçerli olmadan g(getx())geçerli, dil tasarımcıları ilk etapta kaçınmaya çalıştıklarını.

g(getx().ref()); //OK

metodlar sadece 'in sabitliğini thisbilirler, bir değer üzerinde mi yoksa bir değerde mi çağrıldıklarını bilmezler.

C ++ 'da her zaman olduğu gibi, bu kural için bir geçici çözümünüz vardır, ancak derleyiciye açık olarak ne yaptığınızı bildiğinizi bildirmeniz gerekir:

g(const_cast<x&>(getX()));

5

Bunun neden izin verilmediğine dair asıl soru net bir şekilde cevaplandırılmıştır: "büyük olasılıkla bir hata olduğu için".

FWIW, bunun iyi bir teknik olduğunu düşünmeme rağmen nasıl yapılabileceğini göstereceğimi düşündüm .

Bazen geçici olmayan bir başvuru alan bir yönteme geçici bir geçiş yapmak istememizin nedeni, çağıran yöntemin umurunda olmadığı başvuru tarafından döndürülen bir değeri kasten atmaktır. Bunun gibi bir şey:

// Assuming: void Person::GetNameAndAddr(std::string &name, std::string &addr);
string name;
person.GetNameAndAddr(name, string()); // don't care about addr

Önceki cevaplarda açıklandığı gibi, bu derlenmez. Ama bu derler ve doğru çalışır (derleyicimle):

person.GetNameAndAddr(name,
    const_cast<string &>(static_cast<const string &>(string())));

Bu sadece derleyiciye yalan söylemek için döküm kullanabileceğinizi gösterir. Açıkçası, kullanılmayan bir otomatik değişkeni bildirmek ve iletmek çok daha temiz olurdu:

string name;
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr

Bu teknik, yöntemin kapsamına gereksiz bir yerel değişken ekler. Herhangi bir nedenden dolayı, örneğin karışıklık veya hatadan kaçınmak için yöntemde daha sonra kullanılmasını önlemek istiyorsanız, yerel bir blokta gizleyebilirsiniz:

string name;
{
    string unused;
    person.GetNameAndAddr(name, unused); // don't care about addr
}

- Chris


4

Neden hiç istiyorsun X& x = getx();? Sadece kullanın X x = getx();ve RVO'ya güvenin.


3
Çünkü g(getx())yerine aramak istiyorumg(getx().ref())
Alexey Malistov

4
@Alexey, bu gerçek bir sebep değil. Bunu yaparsanız, o zaman mantıklı bir hata var, çünkü gartık ellerinizi alamayacağınız bir şeyi değiştirecek.
Johannes Schaub - litb

3
@ JohannesSchaub-litb belki umrunda değil.
curiousguy

" RVO " olarak adlandırılmadığı sürece "RVO'ya güvenin".
curiousguy

2
@curiousguy: Bu çok kabul gören bir terim. "RVO" olarak atıfta bulunarak kesinlikle yanlış bir şey yoktur.
Köpek yavrusu

4

Kötü geçici çözüm 'değiştirilebilir' anahtar kelimesini içerir. Aslında kötü olmak okuyucu için bir egzersiz olarak bırakılmıştır. Veya buraya bakın: http://www.ddj.com/cpp/184403758


3

Mükemmel bir soru, ve burada daha özlü bir cevap verme girişimim (çünkü birçok yararlı bilgi yorumda ve gürültüyü kazmak zor.)

Doğrudan geçici olana yapılan herhangi bir referans ömrünü uzatacaktır [12.2.5]. Öte yandan, başka bir referansla başlatılan bir referans olmaz (sonuçta aynı geçici olsa bile). Bu mantıklı (derleyici bu referansın nihayetinde neyi ifade ettiğini bilmiyor).

Ancak tüm bu fikir son derece kafa karıştırıcı. Örneğin const X &x = X();geçici olarak xreferans olduğu sürece sürecek , ancak const X &x = X().ref();YAPMAYACAKTIR ( ref()gerçekte neyin döndüğünü kim bilebilir ). İkinci durumda, Xbu hattın sonunda için yıkıcı çağrılır. (Bu önemsiz olmayan bir yıkıcı ile gözlemlenebilir.)

Bu yüzden genellikle kafa karıştırıcı ve tehlikeli görünüyor (neden nesne yaşamlarıyla ilgili kuralları karmaşıklaştırıyor?), Ancak muhtemelen en azından const referanslarına ihtiyaç vardı, bu yüzden standart bu davranışı onlar için ayarlıyor.

[ Sbi yorumundan]: Bir const referansına bağlanmanın geçici bir yaşam süresini arttırdığı gerçeğinin kasıtlı olarak eklenen bir istisna olduğunu unutmayın (manuel optimizasyonlara izin vermek için TTBOMK). Const olmayan başvurular için bir istisna eklenmedi, çünkü const olmayan bir referansa geçici bir bağlamanın büyük olasılıkla bir programcı hatası olduğu görülmüştür.

Tüm geçişler tam ifadenin sonuna kadar devam eder. Bununla birlikte, bunlardan faydalanmak için, sahip olduğunuz bir numaraya ihtiyacınız var ref(). Bu yasal. Programcıya olağandışı bir şeyin devam ettiğini hatırlatmak dışında ekstra çemberin atlaması için iyi bir neden yok gibi görünüyor (yani, değişiklikleri hızlı bir şekilde kaybolacak bir referans parametresi).

[Başka bir sbi yorumu] Stroustrup'un (D&E'de) değerlerin sabit olmayan referanslara bağlanmasına izin vermemek için vermesinin nedeni, Alexey'in g () nesnesinin (sabit olmayan bir fonksiyondan bekleyeceğiniz) referans), ölecek bir nesneyi değiştirir, böylece hiç kimse değiştirilmiş değere ulaşamaz. Bunun büyük olasılıkla bir hata olduğunu söylüyor.


2

"Sabit nesnenin yukarıdaki örnekte sabit olmadığı açıktır, çünkü sabit olmayan fonksiyonlara çağrılara izin verilir. Örneğin, ref () geçici nesneyi değiştirebilir."

Örneğinizde getX () bir const X döndürmez, bu nedenle ref () öğesini X (). Ref () öğesini çağırabileceğiniz şekilde arayabilirsiniz. Const olmayan bir ref döndürüyorsunuz ve böylece const olmayan yöntemleri çağırabilirsiniz, yapamayacağınız şey const olmayan bir referansa ref atamaktır.

SadSidos yorumuyla birlikte bu üç noktanızı yanlış yapar.


1

Alexey'in istediğini yapabileceğimi dilediğim yerde paylaşmak istediğim bir senaryom var. Maya C ++ eklentisinde, bir düğüm özelliğine bir değer elde etmek için aşağıdaki shenanigan'ı yapmak zorundayım:

MFnDoubleArrayData myArrayData;
MObject myArrayObj = myArrayData.create(myArray);   
MPlug myPlug = myNode.findPlug(attributeName);
myPlug.setValue(myArrayObj);

Bu yazmak sıkıcı, bu yüzden aşağıdaki yardımcı fonksiyonları yazdım:

MPlug operator | (MFnDependencyNode& node, MObject& attribute){
    MStatus status;
    MPlug returnValue = node.findPlug(attribute, &status);
    return returnValue;
}

void operator << (MPlug& plug, MDoubleArray& doubleArray){
    MStatus status;
    MFnDoubleArrayData doubleArrayData;
    MObject doubleArrayObject = doubleArrayData.create(doubleArray, &status);
    status = plug.setValue(doubleArrayObject);
}

Ve şimdi yazının başından itibaren kodu yazabilirim:

(myNode | attributeName) << myArray;

Sorun, Visual C ++ dışında derlenmediği için döndürülen geçici değişkeni | operatörünü << operatörünün MPlug referansına bağlayın. Bir referans olmak istiyorum çünkü bu kod birçok kez çağrılır ve MPlug'ın bu kadar çok kopyalanmasını istemezdim. Geçici işlevin sadece ikinci fonksiyonun sonuna kadar yaşamasına ihtiyacım var.

Bu benim senaryom. Sadece Alexey'in tarif ettiklerini yapmak istediği bir örneği göstereceğimi düşündüm. Tüm eleştirileri ve önerileri memnuniyetle karşılıyoruz!

Teşekkürler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.