Dlaczego odniesienie inne niż stałe nie może zostać powiązane z obiektem tymczasowym?

226

Dlaczego niedozwolone jest uzyskiwanie nie stałych odniesień do obiektu tymczasowego, który funkcja getx()zwraca? Oczywiście jest to zabronione przez C ++ Standard, ale interesuje mnie cel takiego ograniczenia, a nie odniesienie do standardu.

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. Oczywiste jest, że żywotność obiektu nie może być przyczyną, ponieważ stałe odwołanie do obiektu nie jest zabronione przez C ++ Standard.
  2. Oczywiste jest, że obiekt tymczasowy nie jest stały w powyższej próbce, ponieważ dozwolone są wywołania funkcji niestałych. Na przykład ref()może zmodyfikować obiekt tymczasowy.
  3. Ponadto ref()pozwala oszukać kompilator i uzyskać link do tego obiektu tymczasowego, co rozwiązuje nasz problem.

Dodatkowo:

Mówią: „przypisanie tymczasowego obiektu do stałej referencji przedłuża jego żywotność” i „Nic nie mówi się o referencjach nie stałych”. Moje dodatkowe pytanie . Czy następujące przypisanie przedłuża żywotność obiektu tymczasowego?

X& x = getx().ref(); // OK
Aleksiej Malistow
źródło
4
Nie zgadzam się z częścią „żywotność obiektu nie może być przyczyną”, tylko dlatego, że w normie jest powiedziane, że przypisanie obiektu tymczasowego do stałej referencji przedłuża żywotność tego obiektu do żywotności stałej referencji. Nic nie mówi się jednak o referencjach non-const ...
SadSido,
3
Cóż, jaka jest przyczyna tego, że „nic nie mówi się o referencjach non-const ...”. To część mojego pytania. Czy jest w tym jakiś sens? Być może autorzy Standardu zapomnieli o referencjach non-const, a wkrótce zobaczymy kolejny podstawowy problem?
Aleksiej Malistow
2
GotW # 88: Kandydat do „Najważniejszego const”. herbutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry
fnieto - Fernando Nieto
4
@Michael: VC wiąże wartości z referencjami innymi niż const. Nazywają to funkcją, ale tak naprawdę to błąd. (Pamiętaj, że nie jest to błąd, ponieważ jest z natury nielogiczny, ale dlatego, że został wyraźnie wykluczony, aby zapobiec głupim błędom.)
sbi 14.10.2009

Odpowiedzi:

97

Z tego artykułu na blogu Visual C ++ o referencjach wartości :

... C ++ nie chce, abyś przypadkowo zmodyfikował tymczasowe, ale bezpośrednie wywoływanie funkcji non-const członka na modyfikowalnej wartości jest jawne, więc jest dozwolone ...

Zasadniczo nie powinieneś próbować modyfikować tymczasowych z tego samego powodu, że są to tymczasowe obiekty i umrą teraz. Powodem, dla którego możesz wywoływać metody non-const, jest to, że, no cóż, możesz robić pewne „głupie” rzeczy, o ile wiesz, co robisz i wyrażasz o tym wyraźne zdanie (np. Używając reinterpret_cast). Ale jeśli powiążesz tymczasowe odniesienie z non-const, możesz nadal przesyłać je „na zawsze” tylko po to, aby zniknąć manipulacja obiektem, ponieważ gdzieś po drodze całkowicie zapomniałeś, że to tymczasowe.

Gdybym był tobą, przemyślałbym projekt moich funkcji. Dlaczego g () akceptuje referencje, czy modyfikuje parametr? Jeśli nie, ustaw jako stałe odniesienie, jeśli tak, dlaczego próbujesz przekazać to tymczasowo, czy nie obchodzi cię to, że modyfikujesz tymczasowo? Dlaczego mimo to getx () zwraca tymczasowe? Jeśli podzielisz się z nami swoim prawdziwym scenariuszem i tym, co próbujesz osiągnąć, możesz uzyskać kilka dobrych wskazówek, jak to zrobić.

Sprzeciwianie się językowi i oszukiwanie kompilatora rzadko rozwiązuje problemy - zwykle stwarza problemy.


Edycja: Odpowiadanie na pytania w komentarzu: 1) X& x = getx().ref(); // OK when will x die?- Nie wiem i nie obchodzi mnie to, ponieważ właśnie to mam na myśli, mówiąc „przeciw językowi”. Język mówi „tymczasowe umierają na końcu instrukcji, chyba że są zobowiązane do stałej referencji, w którym to przypadku umierają, gdy referencja wykracza poza zakres”. Stosując tę ​​regułę, wydaje się, że x jest już martwy na początku następnej instrukcji, ponieważ nie jest związany z const referen (kompilator nie wie, co zwraca ref ()). To tylko przypuszczenie.

2) Jasno określiłem cel: nie wolno modyfikować tymczasowości, ponieważ to po prostu nie ma sensu (ignorowanie odniesień do wartości C ++ 0x). Pytanie „dlaczego wolno mi dzwonić do członków spoza grupy?” jest dobra, ale nie mam lepszej odpowiedzi niż ta, którą już powiedziałem powyżej.

3) Cóż, jeśli mam rację co do x X& x = getx().ref();śmierci na końcu oświadczenia, problemy są oczywiste.

W każdym razie, w oparciu o twoje pytanie i komentarze, nie sądzę, że nawet te dodatkowe odpowiedzi cię zadowolą. Oto ostatnia próba / streszczenie: komisja C ++ zdecydowała, że ​​nie ma sensu modyfikować tymczasowości, dlatego nie zezwoliła na wiązanie z odwołaniami innymi niż stałe. Może to dotyczyć implementacji kompilatora lub dotyczyły również problemów historycznych, nie wiem. Potem pojawił się pewien konkretny przypadek i zdecydowano, że wbrew wszelkim przeciwnościom nadal będą one mogły bezpośrednio modyfikować poprzez wywołanie metody non-const. Ale to wyjątek - generalnie nie wolno modyfikować tymczasowych. Tak, C ++ jest często tak dziwny.

sbk
źródło
2
@sbk: 1) Właściwie właściwe zdanie brzmi: „... na końcu pełnego wyrażenia ...”. „Pełne wyrażenie”, jak sądzę, jest zdefiniowane jako takie, które nie jest podwyrażeniem jakiegoś innego wyrażenia. Czy zawsze jest to to samo, co „koniec wypowiedzi”, nie jestem pewien.
sbi
5
@sbk: 2) Właściwie wolno modyfikować rvalues (tymczasowych). Jest zakazane dla typów wbudowanych ( intitd), ale jest to dozwolone dla typów zdefiniowanych przez użytkownika: (std::string("A")+"B").append("C").
sbi
6
@sbk: 3) Powodem, dla którego Stroustrup podaje (w D&E), aby nie dopuszczać wiązania wartości rv do odwołań nie stałych, jest to, że jeśli Alexey's g()zmodyfikuje obiekt (czego można oczekiwać od funkcji przyjmującej odwołanie inne niż const), zmodyfikowałby obiekt, który umrze, aby nikt nie mógł uzyskać zmodyfikowanej wartości. Mówi, że najprawdopodobniej jest to błąd.
sbi
2
@sbk: Przepraszam, jeśli cię uraziłem, ale nie sądzę, że 2) dręczy. Wartości są po prostu nie stałe, chyba że je uczynisz i możesz je zmienić, chyba że są wbudowane. Trochę czasu zajęło mi zrozumienie, czy np. Za pomocą przykładu ciągu robię coś złego (JFTR: nie robię), więc to rozróżnienie traktuję poważnie.
sbi
5
Zgadzam się z sbi - ta sprawa wcale nie jest głupia . Wszystkie podstawy semantyki ruchów sprawiają, że wartości typu klasy najlepiej zachować jako non-const.
Johannes Schaub - litb
38

W kodzie getx()zwracany jest obiekt tymczasowy, tzw. „Rvalue”. Możesz skopiować wartości do obiektów (zwanych także zmiennymi) lub powiązać je z stałymi referencjami (co wydłuży ich żywotność do końca życia referencji). Nie można powiązać wartości z referencjami innymi niż const.

To była celowa decyzja projektowa, aby zapobiec przypadkowej modyfikacji obiektu, który umrze na końcu wyrażenia:

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

Jeśli chcesz to zrobić, musisz najpierw wykonać kopię lokalną lub obiektu albo powiązać ją z odwołaniem do stałej:

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

Zauważ, że następny standard C ++ będzie zawierał odniesienia do wartości. To, co znacie jako referencje, staje się zatem nazywane „referencją do wartości”. Będziesz mógł powiązać wartości z referencjami do wartości i możesz przeciążać funkcje na „wartości-wartości”:

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

Ideą referencji do wartości jest to, że skoro te obiekty i tak umrą, możesz skorzystać z tej wiedzy i wdrożyć tak zwaną „semantykę ruchu”, pewien rodzaj optymalizacji:

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
sbi
źródło
2
Cześć, to niesamowita odpowiedź. Musisz wiedzieć jedno, g(getx())nie działa, ponieważ jego sygnatura jest g(X& x)i get(x)zwraca obiekt tymczasowy, więc nie możemy powiązać obiektu tymczasowego ( wartości ) z niestałym odwołaniem, prawda? I w twoim pierwszym fragmencie kodu, myślę, że będzie to const X& x2 = getx();zamiast const X& x1 = getx();
SexyBeast,
1
Dziękuję za wskazanie tego błędu w mojej odpowiedzi 5 lat po jego napisaniu! :-/Tak, twoje rozumowanie jest poprawne, choć trochę wstecz: nie możemy powiązać tymczasowych odniesień z wartościami innymi niż const(wartość), a zatem tymczasowe zwrócone przez getx()(i nie get(x)) nie mogą być powiązane z odwołaniem do wartości, do której jest argumentem g().
sbi
Umm, co miałeś na myśli przez getx()(i nie get(x)) ?
SexyBeast,
Kiedy piszę „... getx () (a nie get (x)) ...” , mam na myśli, że nazwa funkcji to getx(), a nie get(x)(jak pisałeś).
sbi
Ta odpowiedź łączy w sobie terminologię. Wartość jest kategorią wyrażenia. Obiekt tymczasowy jest obiektem. Wartość może oznaczać, ale nie musi, obiekt tymczasowy; a obiekt tymczasowy może, ale nie musi, być oznaczony przez wartość.
MM
16

Pokazujesz, że dozwolone jest tworzenie łańcuchów operatorów.

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

Wyrażenie to „getx (). Ref ();” i jest to wykonywane do końca przed przypisaniem do „x”.

Zauważ, że getx () nie zwraca referencji, ale w pełni ukształtowany obiekt w lokalnym kontekście. Obiekt jest chwilowa, ale to nie const, co pozwala na łączenie się z innych metod obliczania wartości lub mają inne skutki uboczne zdarzają.

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

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

Spójrz na koniec tej odpowiedzi, aby uzyskać lepszy przykład tego

Można nie wiążą tymczasowy do odniesienia, ponieważ spowoduje to wygenerowanie odniesienie do obiektu, który zostanie zniszczony na końcu wyrażenia w ten sposób pozostawiając cię z wiszącym odniesienia (który jest zaniedbany, a średnia nie jak niechlujny).

Wartość zwrócona przez ref () jest prawidłowym odwołaniem, ale metoda nie zwraca uwagi na żywotność zwracanego obiektu (ponieważ nie może mieć tej informacji w swoim kontekście). Zasadniczo właśnie wykonałeś odpowiednik:

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

Powodem, dla którego można to zrobić w przypadku stałego odwołania do obiektu tymczasowego, jest to, że standard wydłuża czas życia obiektu tymczasowego do okresu życia odwołania, tak że czas życia obiektów tymczasowych jest przedłużony poza koniec instrukcji.

Pozostaje więc tylko pytanie, dlaczego standard nie zezwala na odwołanie do tymczasowości, aby przedłużyć żywotność obiektu poza koniec instrukcji?

Uważam, że dzieje się tak, ponieważ spowodowałoby to, że kompilator bardzo utrudniłby poprawienie tymczasowych obiektów. Zostało to zrobione dla stałych odwołań do plików tymczasowych, ponieważ ma to ograniczone użycie, a zatem zmusiło cię do zrobienia kopii obiektu, aby zrobić cokolwiek użytecznego, ale zapewnia pewne ograniczone funkcje.

Pomyśl o tej sytuacji:

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

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

Wydłużenie żywotności tego tymczasowego obiektu będzie bardzo mylące.
Podczas gdy następujące:

int const& y = getI();

Daje ci kod, który jest intuicyjny w obsłudze i zrozumieniu.

Jeśli chcesz zmodyfikować wartość, powinieneś zwrócić wartość do zmiennej. Jeśli próbujesz uniknąć kosztu skopiowania obiektu z powrotem z funkcji (wydaje się, że obiekt jest kopią skonstruowaną z powrotem (technicznie jest)). Więc nie przejmuj się, kompilator jest bardzo dobry w „Optymalizacji wartości zwrotu”

Martin York
źródło
3
„Pozostaje więc tylko pytanie, dlaczego standard nie pozwala na odniesienie do tymczasowości, aby przedłużyć żywotność obiektu poza koniec instrukcji?” To jest to! Ci zrozumieć moje pytanie. Ale nie zgadzam się z twoją opinią. Mówisz „uczyń kompilator bardzo trudnym”, ale zrobiono to dla odwołania do const. Mówisz w swoim przykładzie „Uwaga x jest aliasem zmiennej. Jaką zmienną aktualizujesz”. Nie ma problemu. Istnieje unikalna zmienna (tymczasowa). Niektóre obiekty tymczasowe (równe 5) muszą zostać zmienione.
Aleksiej Malistow
@Martin: Zwisające referencje są nie tylko nieporządne. Mogą one prowadzić do poważnych błędów, gdy są dostępne później w metodzie!
mmmmmmmm,
1
@Alexey: Należy pamiętać, że fakt, że powiązanie go z odwołaniem do stałej wydłuża czas życia tymczasowego, to wyjątek, który został dodany celowo (TTBOMK w celu umożliwienia ręcznej optymalizacji). Nie dodano wyjątku dla odwołań niepowiązanych, ponieważ wiązanie tymczasowe z odwołaniem niepowiązanym było najprawdopodobniej błędem programisty.
sbi
1
@alexy: Odwołanie do niewidzialnej zmiennej! Nie takie intuicyjne.
Martin York
const_cast<x&>(getX());nie ma sensu
ciekawy
10

Dlaczego omówiono w C ++ FAQ ( pogrubiona kopalnia):

W języku C ++ odwołania nie będące stałymi mogą się wiązać z wartościami lv, a stałe odwołania mogą wiązać się z wartościami lvalu lub wartościami rvalu, ale nie ma nic, co mogłoby wiązać się z wartością inną niż const. Ma to na celu ochronę ludzi przed zmianą wartości tymczasowych, które są niszczone, zanim ich nowa wartość będzie mogła zostać użyta . Na przykład:

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

Gdyby to incr (0) było dozwolone albo tymczasowo, którego nikt nigdy nie widział, zwiększyłoby się, albo - co gorsza - wartość 0 wyniósłaby 1. To drugie brzmi głupio, ale tak naprawdę był taki błąd we wczesnych kompilatorach Fortrana, które ustawiały poza miejscem w pamięci do przechowywania wartości 0.

Tony Delroy
źródło
Byłoby zabawnie widzieć twarz programisty ugryzionego przez ten „zerowy błąd” w Fortranie! x * 0 daje x? Co? Co??
John D,
Ten ostatni argument jest szczególnie słaby. Żaden kompilator, o którym warto wspomnieć, nigdy nie zmieniłby wartości od 0 do 1, a nawet interpretował incr(0);w taki sposób. Oczywiście, gdyby było to dozwolone, byłoby to interpretowane jako utworzenie tymczasowej liczby całkowitej i przekazanie jej doincr()
user3204459
6

Głównym problemem jest to

g(getx()); //error

jest logicznym błędem: gmodyfikuje wynik, getx()ale nie masz szans na sprawdzenie zmodyfikowanego obiektu. Gdyby gnie musiał modyfikować swojego parametru, nie wymagałby odwołania do wartości, mógłby wziąć parametr według wartości lub stałej.

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

jest poprawna, ponieważ czasami trzeba ponownie użyć wyniku wyrażenia i jest całkiem jasne, że masz do czynienia z obiektem tymczasowym.

Jednak nie można tego zrobić

X& x = getx(); // error

ważne bez g(getx())unieważniania, czego projektanci języków starali się przede wszystkim unikać.

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

jest poprawny, ponieważ metody wiedzą tylko o thisstałości parametru , nie wiedzą, czy są wywoływane na wartości lvalue czy rvalue.

Jak zawsze w C ++, masz obejście tej reguły, ale musisz zasygnalizować kompilatorowi, że wiesz, co robisz, jawnie:

g(const_cast<x&>(getX()));
Dan Berindei
źródło
5

Wydaje się, że na pierwotne pytanie, dlaczego nie jest to dozwolone, udzielono jasnej odpowiedzi: „ponieważ najprawdopodobniej jest to błąd”.

FWIW, myślałem, że pokażę, jak to zrobić, chociaż nie sądzę, że to dobra technika.

Powodem, dla którego czasami chcę przekazać tymczasową metodę przyjmującą odwołanie inne niż stałe, jest celowe odrzucenie wartości zwracanej przez odwołanie, o którą nie obchodzi metoda wywołująca. Coś takiego:

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

Jak wyjaśniono w poprzednich odpowiedziach, to się nie kompiluje. Ale to kompiluje się i działa poprawnie (z moim kompilatorem):

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

To tylko pokazuje, że możesz użyć rzutowania, by okłamać kompilator. Oczywiście znacznie łatwiej byłoby zadeklarować i przekazać nieużywaną zmienną automatyczną:

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

Ta technika wprowadza niepotrzebną zmienną lokalną do zakresu metody. Jeśli z jakiegoś powodu chcesz uniemożliwić użycie go później w metodzie, np. Aby uniknąć pomyłek lub błędów, możesz ukryć go w lokalnym bloku:

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

- Chris

Chris Pearson
źródło
4

Dlaczego miałbyś kiedykolwiek chcieć X& x = getx();? Wystarczy użyć X x = getx();i polegać na RVO.

DevFred
źródło
3
Ponieważ chcę g(getx())raczej zadzwonić niżg(getx().ref())
Aleksiej Malistow
4
@Alexey, to nie jest prawdziwy powód. Jeśli to zrobisz, to napotkasz logiczny błąd, ponieważ gzamierza zmodyfikować coś, czego nie możesz już zdobyć.
Johannes Schaub - litb
3
@ JohannesSchaub-litb może go to nie obchodzi.
ciekawy
polegaj na RVO ”, ale nie nazywa się to „RVO”.
ciekawy
2
@curiousguy: To bardzo akceptowany termin. Nie ma absolutnie nic złego w określaniu go jako „RVO”.
Szczeniak
4

Obejście zła obejmuje słowo kluczowe „zmienne”. W rzeczywistości bycie złym jest dla czytelnika ćwiczeniem. Lub zobacz tutaj: http://www.ddj.com/cpp/184403758

Paweł
źródło
3

Doskonałe pytanie, a oto moja próba bardziej zwięzłej odpowiedzi (ponieważ wiele użytecznych informacji znajduje się w komentarzach i trudno jest odszukać w hałasie).

Wszelkie odniesienia związane bezpośrednio z osobą tymczasową przedłuży jej życie [12.2.5]. Z drugiej strony odwołanie zainicjowane innym odwołaniem nie będzie (nawet jeśli ostatecznie będzie takie samo tymczasowe). Ma to sens (kompilator nie wie, do czego ostatecznie odnosi się to odniesienie).

Ale cały ten pomysł jest bardzo mylący. Np. Sprawi const X &x = X();, że tymczasowe będzie trwać tak długo, jak xodniesienie, ale const X &x = X().ref();NIE będzie (kto wie, co ref()faktycznie powrócił). W tym drugim przypadku Xwywoływany jest destruktor dla końca tej linii. (Można to zaobserwować za pomocą nietrywialnego destruktora).

Wydaje się więc ogólnie mylące i niebezpieczne (po co komplikować reguły dotyczące czasu życia obiektów?), Ale przypuszczalnie istniała potrzeba przynajmniej stałych odwołań, więc standard określa dla nich takie zachowanie.

[Od komentarza sbi ]: Zauważ, że fakt, że powiązanie go z odwołaniem do stałej wydłuża czas życia tymczasowego to wyjątek, który został celowo dodany (TTBOMK w celu umożliwienia ręcznej optymalizacji). Nie dodano wyjątku dla odwołań niepowiązanych, ponieważ wiązanie tymczasowe z odwołaniem niepowiązanym było najprawdopodobniej błędem programisty.

Wszystkie tymczasowe istnieją do końca pełnego wyrażenia. Jednak aby z nich skorzystać, potrzebujesz takiej sztuczki, jaką masz ref(). To legalne. Dodatkowy obręcz nie wydaje się być dobrym powodem, aby przypomnieć programiście, że dzieje się coś niezwykłego (mianowicie parametr odniesienia, którego modyfikacje zostaną szybko utracone).

[Kolejny komentarz sbi ] Powodem, dla którego Stroustrup podaje (w D&E) za niedopuszczenie wiązania wartości rvalu do odwołań nie-stałych jest to, że jeśli g () Alexeya zmodyfikuje obiekt (czego można oczekiwać od funkcji przyjmującej non-const referencja), zmodyfikowałby obiekt, który umrze, aby nikt nie mógł uzyskać zmodyfikowanej wartości. Mówi, że najprawdopodobniej jest to błąd.

DS.
źródło
2

„Oczywiste jest, że obiekt tymczasowy nie jest stały w powyższej próbce, ponieważ dozwolone są wywołania funkcji niestałych. Na przykład ref () może modyfikować obiekt tymczasowy.”

W twoim przykładzie getX () nie zwraca stałej X, więc możesz wywołać ref () w taki sam sposób, jak możesz wywołać X (). Ref (). Zwracane jest odwołanie non const, więc można wywoływać metody non const, nie można tego przypisać do odwołania non const.

Wraz z komentarzem SadSidos powoduje to, że trzy punkty są nieprawidłowe.

Patrick
źródło
1

Mam scenariusz, którym chciałbym się podzielić, gdzie chciałbym zrobić to, o co prosi Alexey. We wtyczce Maya C ++ muszę wykonać następujące shenanigan, aby uzyskać wartość atrybutu węzła:

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

Pisanie tego jest żmudne, dlatego napisałem następujące funkcje pomocnicze:

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);
}

A teraz mogę napisać kod od początku postu jako:

(myNode | attributeName) << myArray;

Problem polega na tym, że nie kompiluje się poza Visual C ++, ponieważ próbuje powiązać zmienną tymczasową zwróconą z | operator do odwołania MPlug operatora <<. Chciałbym, aby był to odnośnik, ponieważ ten kod jest wywoływany wiele razy i wolałbym, aby MPlug nie był tak często kopiowany. Potrzebuję tylko tymczasowego obiektu, aby przeżyć do końca drugiej funkcji.

To mój scenariusz. Pomyślałem, że pokażę przykład, w którym chciałbym zrobić to, co opisuje Aleksiej. Z zadowoleniem przyjmuję wszystkie krytyki i sugestie!

Dzięki.

Robert Trussardi
źródło