Kenapa referensi non-const tidak dapat mengikat ke objek sementara?

226

Mengapa tidak diizinkan untuk mendapatkan referensi non-const ke objek sementara, yang fungsinya getx()kembali? Jelas, ini dilarang oleh Standar C ++ tetapi saya tertarik pada tujuan pembatasan tersebut, bukan referensi ke standar.

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. Jelas bahwa masa hidup objek tidak dapat menjadi penyebabnya, karena referensi konstan ke objek adalah tidak dilarang oleh Standar C ++.
  2. Jelas bahwa objek sementara tidak konstan dalam sampel di atas, karena panggilan ke fungsi yang tidak konstan diizinkan. Misalnya,ref() bisa memodifikasi objek sementara.
  3. Sebagai tambahan, ref() memungkinkan Anda untuk menipu kompilator dan mendapatkan tautan ke objek sementara ini dan itu memecahkan masalah kami.

Sebagai tambahan:

Mereka mengatakan "menetapkan objek sementara ke referensi const memperpanjang umur objek ini" dan "Tidak ada yang dikatakan tentang referensi non-const". Pertanyaan tambahan saya . Apakah tugas berikut memperpanjang masa objek sementara?

X& x = getx().ref(); // OK
Alexey Malistov
sumber
4
Saya tidak setuju dengan bagian "masa objek tidak dapat menjadi penyebab", hanya karena dinyatakan dalam standar, bahwa menetapkan objek sementara ke referensi const memperpanjang masa hidup objek ini ke masa hidup referensi const. Tidak ada yang dikatakan tentang referensi non-const ...
SadSido
3
Nah, apa penyebab dari itu "Tidak ada yang dikatakan tentang referensi non-const ...". Itu adalah bagian dari pertanyaan saya. Apakah ada perasaan dalam hal ini? Mungkin penulis Standar hanya lupa tentang referensi non-const dan segera kita akan melihat Core Issue berikutnya?
Alexey Malistov
2
GotW # 88: Calon Untuk "const Paling Penting". herbalutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry
fnieto - Fernando Nieto
4
@Michael: VC mengikat nilai untuk referensi non-const. Mereka menyebutnya fitur, tetapi sebenarnya ini adalah bug. (Catatan bahwa itu bukan bug karena itu inheren tidak logis, tapi karena diperintah secara eksplisit untuk mencegah kesalahan konyol.)
sbi

Jawaban:

97

Dari artikel blog Visual C ++ ini tentang referensi nilai :

... C ++ tidak ingin Anda memodifikasi temporer secara tidak sengaja, tetapi langsung memanggil fungsi non-const member pada nilai yang dapat dimodifikasi adalah eksplisit, jadi diizinkan ...

Pada dasarnya, Anda tidak boleh mencoba mengubah temporari karena alasan mereka temporer dan akan mati kapan saja sekarang. Alasan Anda diizinkan memanggil metode non-const adalah karena, Anda boleh melakukan beberapa hal "bodoh" selama Anda tahu apa yang Anda lakukan dan Anda eksplisit tentang hal itu (seperti, menggunakan reinterpret_cast). Tetapi jika Anda mengikat sementara ke referensi non-const, Anda bisa terus menyebarkannya "selamanya" hanya untuk menghilangkan manipulasi objek, karena di suatu tempat di mana Anda benar-benar lupa ini adalah sementara.

Jika saya jadi Anda, saya akan memikirkan kembali desain fungsi saya. Mengapa g () menerima referensi, apakah itu memodifikasi parameter? Jika tidak, buatlah itu sebagai referensi, jika ya, mengapa Anda mencoba memberikan sementara untuk itu, tidakkah Anda peduli itu hanya sementara yang Anda modifikasi? Kenapa getx () kembali sementara? Jika Anda berbagi dengan kami skenario nyata Anda dan apa yang ingin Anda capai, Anda mungkin mendapatkan beberapa saran bagus tentang bagaimana melakukannya.

Melawan bahasa dan menipu kompiler jarang memecahkan masalah - biasanya itu menciptakan masalah.


Sunting: Mengatasi pertanyaan dalam komentar: 1) X& x = getx().ref(); // OK when will x die?- Saya tidak tahu dan saya tidak peduli, karena inilah yang saya maksud dengan "menentang bahasa". Bahasa mengatakan "temporaries mati pada akhir pernyataan, kecuali mereka terikat dengan referensi konstan, dalam hal ini mereka mati ketika referensi keluar dari ruang lingkup". Menerapkan aturan itu, tampaknya x sudah mati di awal pernyataan berikutnya, karena itu tidak terikat dengan referensi const (kompiler tidak tahu apa yang ref () kembali). Namun ini hanya dugaan saja.

2) Saya menyatakan tujuannya dengan jelas: Anda tidak diperbolehkan untuk mengubah temporaries, karena itu tidak masuk akal (mengabaikan nilai rujukan C ++ 0x). Pertanyaannya "lalu mengapa saya diizinkan memanggil anggota non-const?" adalah jawaban yang bagus, tetapi saya tidak memiliki jawaban yang lebih baik daripada jawaban yang telah saya sebutkan di atas.

3) Nah, jika saya benar tentang x dalam X& x = getx().ref();sekarat di akhir pernyataan, masalahnya jelas.

Ngomong-ngomong, berdasarkan pertanyaan dan komentar Anda, saya rasa jawaban ekstra ini tidak akan memuaskan Anda. Berikut ini adalah upaya / ringkasan terakhir: Komite C ++ memutuskan tidak masuk akal untuk mengubah temporari, oleh karena itu, mereka melarang pengikatan pada referensi non-const. Mungkin beberapa implementasi kompiler atau masalah bersejarah juga terlibat, saya tidak tahu. Kemudian, beberapa kasus spesifik muncul, dan diputuskan bahwa melawan segala rintangan, mereka masih akan memungkinkan modifikasi langsung melalui pemanggilan metode non-const. Tapi itu pengecualian - Anda biasanya tidak diizinkan mengubah temporer. Ya, C ++ seringkali aneh.

sbk
sumber
2
@sbk: 1) Sebenarnya, frasa yang tepat adalah: "... di akhir ekspresi penuh ...". Saya percaya, "ekspresi penuh" didefinisikan sebagai ekspresi yang bukan merupakan sub ekspresi dari ekspresi lain. Apakah ini selalu sama dengan "akhir dari pernyataan", saya tidak yakin.
sbi
5
@sbk: 2) Sebenarnya, Anda yang diperbolehkan untuk memodifikasi rvalues (temporaries). Itu dilarang untuk built-in jenis ( intdll), tetapi diperbolehkan untuk jenis yang ditetapkan pengguna: (std::string("A")+"B").append("C").
sbi
6
@sbk: 3) Alasan Stroustrup memberi (dalam D&E) untuk melarang pengikatan nilai-nilai ke referensi non-const adalah bahwa, jika Alexey's g()akan memodifikasi objek (yang Anda harapkan dari fungsi mengambil referensi non-const), itu akan memodifikasi objek yang akan mati, jadi tidak ada yang bisa mendapatkan nilai yang dimodifikasi. Dia mengatakan bahwa ini, kemungkinan besar, adalah kesalahan.
sbi
2
@ sbk: Maaf kalau saya telah menyinggung Anda, tapi saya pikir 2) tidak menghiraukan. Nilai hanya bukan konst kecuali jika Anda membuatnya dan Anda dapat mengubahnya, kecuali jika itu built-in. Butuh beberapa saat untuk memahami apakah, dengan, misalnya, contoh string, saya melakukan sesuatu yang salah (JFTR: Saya tidak), jadi saya cenderung menganggap perbedaan ini serius.
sbi
5
Saya setuju dengan sbi - masalah ini sama sekali tidak menarik. Ini semua adalah dasar dari semantik gerakan bahwa nilai tipe kelas paling baik disimpan non-const.
Johannes Schaub - litb
38

Dalam kode Anda getx()mengembalikan objek sementara, yang disebut "nilai". Anda dapat menyalin nilai ke objek (alias. Variabel) atau mengikat mereka ke referensi const (yang akan memperpanjang waktu hidup mereka sampai akhir kehidupan referensi). Anda tidak dapat mengikat nilai ke referensi non-const.

Ini adalah keputusan desain yang disengaja untuk mencegah pengguna memodifikasi objek secara tidak sengaja yang akan mati di akhir ekspresi:

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

Jika Anda ingin melakukan ini, Anda harus membuat salinan lokal atau objek terlebih dahulu atau mengikatnya ke referensi const:

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

Perhatikan bahwa standar C ++ berikutnya akan mencakup referensi nilai. Oleh karena itu, apa yang Anda ketahui sebagai rujukan disebut "referensi nilai". Anda akan diizinkan untuk mengikat nilai ke nilai referensi dan Anda dapat membebani fungsi pada "nilai-nilai":

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

Gagasan di balik referensi nilai adalah bahwa, karena benda-benda ini akan mati, Anda dapat mengambil keuntungan dari pengetahuan itu dan mengimplementasikan apa yang disebut "pindahkan semantik", semacam optimasi tertentu:

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
sumber
2
Hai, ini jawaban yang luar biasa. Perlu tahu satu hal, g(getx())tidak bekerja karena tanda tangan adalah g(X& x)dan get(x)mengembalikan sebuah objek sementara, jadi kami tidak bisa mengikat objek sementara ( nilai p ) untuk referensi non-konstan, yang benar? Dan dalam potongan kode pertama Anda, saya pikir itu akan menjadi const X& x2 = getx();bukan const X& x1 = getx();..
SexyBeast
1
Terima kasih telah menunjukkan bug ini dalam jawaban saya 5 tahun setelah saya menulisnya! :-/Ya, alasan Anda benar, meskipun sedikit terbelakang: Kami tidak dapat mengikat sementara ke constreferensi non- (nilai), dan oleh karena itu sementara dikembalikan oleh getx()(dan tidak get(x)) tidak dapat terikat pada referensi nilai yang menjadi alasan argumen tersebut g().
sbi
Umm, apa maksudmu dengan getx()(dan tidak get(x)) ?
SexyBeast
Ketika saya menulis "... getx () (dan tidak mendapatkan (x)) ..." , maksud saya adalah nama fungsinya getx(), dan bukan get(x)(seperti yang Anda tulis).
sbi
Jawaban ini mencampuradukkan terminologi. Nilai adalah kategori ekspresi. Objek sementara adalah objek. Nilai mungkin atau mungkin tidak menunjukkan objek sementara; dan objek sementara mungkin dilambangkan dengan nilai.
MM
16

Apa yang Anda tunjukkan adalah bahwa rantai operator diperbolehkan.

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

Ungkapannya adalah 'getx (). Ref ();' dan ini dieksekusi sampai selesai sebelum penugasan ke 'x'.

Perhatikan bahwa getx () tidak mengembalikan referensi tetapi objek yang sepenuhnya terbentuk ke dalam konteks lokal. Objek bersifat sementara tetapi bukan const, sehingga memungkinkan Anda memanggil metode lain untuk menghitung nilai atau memiliki efek samping lainnya terjadi.

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

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

Lihatlah akhir dari jawaban ini untuk contoh yang lebih baik dari ini

Anda tidak dapat mengikat sementara ke referensi karena hal itu akan menghasilkan referensi ke objek yang akan dihancurkan di akhir ungkapan sehingga meninggalkan Anda dengan referensi menggantung (yang tidak rapi dan standar tidak suka berantakan).

Nilai yang dikembalikan oleh ref () adalah referensi yang valid tetapi metode ini tidak memperhatikan umur objek yang dikembalikan (karena tidak dapat memiliki informasi dalam konteksnya). Anda pada dasarnya baru saja melakukan yang setara dengan:

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

Alasan tidak apa-apa untuk melakukan ini dengan referensi const ke objek sementara adalah bahwa standar memperpanjang umur sementara untuk umur referensi sehingga umur objek sementara diperpanjang melebihi akhir pernyataan.

Jadi satu-satunya pertanyaan yang tersisa adalah mengapa standar tidak ingin mengizinkan referensi ke temporaries untuk memperpanjang umur objek melampaui akhir pernyataan?

Saya percaya itu karena hal itu akan membuat kompiler sangat sulit untuk mendapatkan yang benar untuk objek sementara. Itu dilakukan untuk referensi const ke temporaries karena ini memiliki penggunaan terbatas dan dengan demikian memaksa Anda untuk membuat salinan objek untuk melakukan sesuatu yang bermanfaat tetapi memang menyediakan beberapa fungsi terbatas.

Pikirkan situasi ini:

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

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

Memperpanjang umur objek sementara ini akan sangat membingungkan.
Sedangkan yang berikut ini:

int const& y = getI();

Akan memberi Anda kode yang intuitif untuk digunakan dan dipahami.

Jika Anda ingin mengubah nilai, Anda harus mengembalikan nilai ke variabel. Jika Anda mencoba untuk menghindari biaya menyalin kembali obejct dari fungsi (karena tampaknya objek tersebut adalah salinan yang dibangun kembali (secara teknis itu)). Maka jangan ganggu kompilernya sangat bagus di 'Return Value Optimization'

Martin York
sumber
3
"Jadi satu-satunya pertanyaan yang tersisa adalah mengapa standar tidak ingin memungkinkan referensi ke temporaries untuk memperpanjang umur objek di luar akhir pernyataan?" Hanya itu saja! Anda mengerti pertanyaan saya. Tapi saya tidak setuju dengan pendapat Anda. Anda mengatakan "membuat kompiler sangat sulit" tetapi itu dilakukan untuk referensi const. Anda mengatakan dalam sampel Anda "Catatan x adalah alias untuk variabel. Variabel apa yang Anda perbarui." Tidak masalah. Ada variabel unik (sementara). Beberapa objek sementara (sama dengan 5) harus diubah.
Alexey Malistov
@ Martin: Menggantung referensi tidak hanya berantakan. Mereka dapat menyebabkan bug serius ketika diakses nanti dalam metode ini!
mmmmmmmm
1
@ Alexey: Perhatikan bahwa fakta bahwa mengikatnya ke referensi const meningkatkan masa pakai sementara adalah pengecualian yang telah ditambahkan dengan sengaja (TTBOMK untuk memungkinkan optimalisasi manual). Tidak ada pengecualian yang ditambahkan untuk referensi non-const, karena pengikatan temporer ke referensi non-const dianggap sebagai kesalahan programmer.
sbi
1
@alexy: Referensi ke variabel yang tak terlihat! Bukan itu intuatif.
Martin York
const_cast<x&>(getX());tidak masuk akal
curiousguy
10

Mengapa dibahas dalam C ++ FAQ ( boldfacing mine):

Dalam C ++, referensi non-const dapat mengikat nilai-nilai dan referensi const dapat mengikat nilai-nilai atau nilai-nilai, tetapi tidak ada yang dapat mengikat nilai non-const. Itu untuk melindungi orang dari mengubah nilai-nilai sementara yang dihancurkan sebelum nilai baru mereka dapat digunakan . Sebagai contoh:

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

Jika incr (0) itu dibolehkan baik beberapa sementara yang tidak ada yang pernah melihat akan bertambah atau - jauh lebih buruk - nilai 0 akan menjadi 1. Yang terakhir terdengar konyol, tetapi sebenarnya ada bug seperti itu di kompiler Fortran awal yang menetapkan selain lokasi memori untuk menyimpan nilai 0.

Tony Delroy
sumber
Akan lucu melihat wajah programmer yang digigit Fortran "zero bug"! x * 0 memberi x? Apa? Apa??
John D
Argumen terakhir itu sangat lemah. Tidak ada kompiler yang layak disebutkan yang akan benar-benar mengubah nilai 0 ke 1, atau bahkan menginterpretasikan incr(0);sedemikian rupa. Jelas, jika ini diizinkan, itu akan ditafsirkan sebagai menciptakan integer sementara dan meneruskannya keincr()
user3204459
6

Masalah utamanya adalah itu

g(getx()); //error

adalah kesalahan logis: gmemodifikasi hasil getx()tetapi Anda tidak memiliki kesempatan untuk memeriksa objek yang dimodifikasi. Jika gtidak perlu mengubah parameternya maka itu tidak akan memerlukan referensi nilai, itu bisa mengambil parameter dengan nilai atau dengan referensi const.

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

valid karena Anda terkadang perlu menggunakan kembali hasil ekspresi, dan cukup jelas bahwa Anda berurusan dengan objek sementara.

Namun itu tidak mungkin dilakukan

X& x = getx(); // error

valid tanpa membuat g(getx())valid, itulah yang para desainer bahasa coba hindari sejak awal.

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

valid karena metode hanya tahu tentang kekonstanan this, mereka tidak tahu apakah mereka dipanggil berdasarkan nilai atau nilai.

Seperti biasa di C ++, Anda memiliki solusi untuk aturan ini tetapi Anda harus memberi sinyal kepada kompiler bahwa Anda tahu apa yang Anda lakukan dengan menjadi eksplisit:

g(const_cast<x&>(getX()));
Dan Berindei
sumber
5

Sepertinya pertanyaan awal mengapa ini tidak diizinkan telah dijawab dengan jelas: "karena kemungkinan besar kesalahan".

FWIW, saya pikir saya akan menunjukkan bagaimana itu bisa dilakukan, meskipun saya pikir itu bukan teknik yang baik.

Alasan saya kadang-kadang ingin meneruskan sementara ke metode mengambil referensi non-const adalah untuk sengaja membuang nilai yang dikembalikan oleh-referensi bahwa metode pemanggilan tidak peduli. Sesuatu seperti ini:

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

Seperti yang dijelaskan dalam jawaban sebelumnya, itu tidak dikompilasi. Tetapi ini mengkompilasi dan bekerja dengan benar (dengan kompiler saya):

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

Ini hanya menunjukkan bahwa Anda dapat menggunakan casting untuk berbohong kepada kompiler. Jelas, akan jauh lebih bersih untuk mendeklarasikan dan meneruskan variabel otomatis yang tidak digunakan:

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

Teknik ini memang memperkenalkan variabel lokal yang tidak dibutuhkan ke dalam ruang lingkup metode. Jika karena alasan tertentu Anda ingin mencegahnya agar tidak digunakan nanti dalam metode, misalnya, untuk menghindari kebingungan atau kesalahan, Anda bisa menyembunyikannya di blok lokal:

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

- Chris

Chris Pearson
sumber
4

Mengapa kamu menginginkannya X& x = getx();? Cukup gunakan X x = getx();dan mengandalkan RVO.

DevFred
sumber
3
Karena saya ingin menelepon g(getx())daripadag(getx().ref())
Alexey Malistov
4
@ Alexey, itu bukan alasan sebenarnya. Jika Anda melakukan itu, maka Anda memiliki kesalahan logis di mana-mana, karena gakan mengubah sesuatu yang tidak bisa Anda dapatkan lagi.
Johannes Schaub - litb
3
@ JohannesSchaub-litb mungkin dia tidak peduli.
curiousguy
" mengandalkan RVO " kecuali itu tidak disebut "RVO".
curiousguy
2
@curiousguy: Itu istilah yang sangat diterima untuk itu. Sama sekali tidak ada yang salah dengan menyebutnya sebagai "RVO".
Puppy
4

Solusi jahat melibatkan kata kunci 'bisa berubah'. Sebenarnya menjadi jahat dibiarkan sebagai latihan bagi pembaca. Atau lihat di sini: http://www.ddj.com/cpp/184403758

paul
sumber
3

Pertanyaan yang sangat bagus, dan inilah usaha saya untuk jawaban yang lebih ringkas (karena banyak info bermanfaat ada di komentar dan sulit untuk digali dalam keributan.)

Referensi apa pun yang terikat langsung dengan sementara akan memperpanjang umurnya [12.2.5]. Di sisi lain, referensi yang diinisialisasi dengan referensi lain tidak akan (bahkan jika itu pada akhirnya sama sementara). Itu masuk akal (kompiler tidak tahu referensi apa yang akhirnya merujuk).

Tetapi seluruh gagasan ini sangat membingungkan. Misalnya const X &x = X();akan membuat sementara berlangsung selama xreferensi, tetapi const X &x = X().ref();TIDAK akan (siapa yang tahu apa yang ref()sebenarnya dikembalikan). Dalam kasus terakhir, destructor untuk Xdipanggil pada akhir baris ini. (Ini dapat diamati dengan destruktor non-sepele.)

Jadi tampaknya secara umum membingungkan dan berbahaya (mengapa menyulitkan aturan tentang masa hidup objek?), Tetapi mungkin ada kebutuhan setidaknya untuk referensi const, sehingga standar mengatur perilaku ini untuk mereka.

[Dari komentar sbi ]: Perhatikan bahwa fakta bahwa mengikatnya ke referensi const meningkatkan kehidupan sementara adalah pengecualian yang telah ditambahkan dengan sengaja (TTBOMK untuk memungkinkan optimalisasi manual). Tidak ada pengecualian yang ditambahkan untuk referensi non-const, karena pengikatan temporer ke referensi non-const dianggap sebagai kesalahan programmer.

Semua temporari bertahan sampai akhir ekspresi penuh. Untuk memanfaatkannya, Anda perlu trik seperti yang Anda miliki ref(). Itu legal. Kelihatannya tidak ada alasan yang baik bagi lingkaran ekstra untuk melompati, kecuali untuk mengingatkan programmer bahwa sesuatu yang tidak biasa sedang terjadi (yaitu, parameter referensi yang modifikasinya akan cepat hilang).

[ Komentar sbi lain ] Alasan Stroustrup memberi (dalam D&E) untuk tidak mengikat pengikatan nilai ke referensi non-const adalah bahwa, jika Alexey's g () akan memodifikasi objek (yang Anda harapkan dari fungsi mengambil non-const referensi), itu akan memodifikasi objek yang akan mati, jadi tidak ada yang bisa mendapatkan nilai yang dimodifikasi. Dia mengatakan bahwa ini, kemungkinan besar, adalah kesalahan.

DS.
sumber
2

"Jelas bahwa objek sementara tidak konstan dalam sampel di atas, karena panggilan ke fungsi yang tidak konstan diizinkan. Misalnya, ref () dapat memodifikasi objek sementara."

Dalam contoh Anda getX () tidak mengembalikan sebuah konstanta X sehingga Anda dapat memanggil ref () dengan cara yang sama seperti Anda bisa memanggil X (). Ref (). Anda mengembalikan ref non const dan dengan demikian dapat memanggil metode non const, yang tidak bisa Anda lakukan adalah menetapkan ref ke referensi non const.

Bersamaan dengan komentar SadSidos ini membuat tiga poin Anda salah.

Patrick
sumber
1

Saya memiliki skenario yang ingin saya bagikan di mana saya berharap dapat melakukan apa yang diminta Alexey. Dalam plugin Maya C ++, saya harus melakukan shenanigan berikut untuk mendapatkan nilai ke atribut node:

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

Ini membosankan untuk menulis, jadi saya menulis fungsi pembantu berikut:

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

Dan sekarang saya dapat menulis kode dari awal posting sebagai:

(myNode | attributeName) << myArray;

Masalahnya adalah ia tidak dikompilasi di luar Visual C ++, karena ia mencoba untuk mengikat variabel sementara yang dikembalikan dari | operator ke referensi MPlug dari << operator. Saya ingin itu menjadi referensi karena kode ini disebut berkali-kali dan saya lebih suka tidak disalin MPlug begitu banyak. Saya hanya perlu objek sementara untuk hidup sampai akhir fungsi kedua.

Nah, ini skenario saya. Hanya berpikir saya akan menunjukkan contoh di mana orang ingin melakukan apa yang dijelaskan Alexey. Saya menyambut semua kritik dan saran!

Terima kasih.

Robert Trussardi
sumber