Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > C/C++
You last visited: Today at 05:46

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Pass by value oder const reference

Discussion on Pass by value oder const reference within the C/C++ forum part of the Coders Den category.

Reply
 
Old   #1
 
_Roman_'s Avatar
 
elite*gold: 0
Join Date: May 2010
Posts: 1,620
Received Thanks: 237
Pass by value oder const reference

Ich verstehe nicht so ganz, welche Variante wann sinnvoller ist und warum. Beispielsweise

Code:
void foo(const std::string &text)
{
     var = text;
}

void foo(std::string text)
{
     var = text;
}
var wäre in dem Fall eine Membervariable. Welche Variante davon ist effizienter? Ich hab jetzt eine Weile rumgelesen und verstehe nicht so ganz, warum ich die zweite Variante nehmen soll wenn ich den Parameter kopiere. Habe dazu folgendes gefunden:

Quote:
The const reference approach is efficient if we don’t make a copy of the passed argument. However, if we do, and the function is called with an rvalue, then we miss the opportunity of moving this argument instead of making a copy. So, in summary, pass by const reference is optimal if no copies are made. Otherwise, it misses out on rvalue arguments.

The by-value approach is efficient if we do make a copy of the passed argument. However, if we don’t, and the function is called with an lvalue, then we make an unnecessary copy. So, in summary, pass by value is optimal if we know for sure we are going to copy the argument. Otherwise, it adds a copy overhead in case of an lvalue argument.
Welche Variante soll ich dann nehmen, wenn die Funktion nur mit lvalues arbeitet?
_Roman_ is offline  
Old 10/09/2015, 14:16   #2
 
elite*gold: 0
Join Date: Mar 2010
Posts: 360
Received Thanks: 132
void foo(std::string text);
erstellt eine Kopie und ordnet diese var zu.
var und text werden nicht verändert -> Ressourcen Verschwendung, eine überflüssige Kopie.

void foo(const std::string &text);
erstellt keine Kopie sondern übergibt eine const Referenz.
var = text ist eine legitime Zuweisung, sofern var vom Typ const std::string ist.
Du veränderst var und text nicht, daher ist dies der richtige Ansatz.
Daifoku is offline  
Old 10/09/2015, 14:36   #3
 
Padmak's Avatar
 
elite*gold: 58
Join Date: Jun 2008
Posts: 2,311
Received Thanks: 8,420
var wird sehr wohl verändert, und zwar bei beiden Ansätzen

Der einzige Unterschied:
Bei const std::string& *muss* text kopiert werden, um var auf den gleichen Wert setzen zu können

Bei std::string braucht man theoretisch 2 Kopien, einmal beim Aufrufen der Funktion und einmal beim Zuweisen, allerdings sagt der Text den du selbst oben reinkopiert hast aus, dass bei der zweiten Methode der Compiler die text-Variable auch genauso gut in die var-Variable rein *MOVEN* kann.

Du hast dir doch eigentlich deine Frage schon selbst beantwortet

Padmak
Padmak is offline  
Thanks
1 User
Old 10/09/2015, 16:01   #4
 
elite*gold: 46
Join Date: Oct 2010
Posts: 782
Received Thanks: 525
Quote:
Originally Posted by Padmak View Post
dass bei der zweiten Methode der Compiler die text-Variable auch genauso gut in die var-Variable rein *MOVEN* kann.
Nein das darf der Compiler nicht. Wenn dann wird der Move Konstruktor vom Argument (also von text) aufgerufen. Da man aber in der Funktion alleinigen Zugriff auf das Objekt text hat und wenn man es in der Funktion nicht mehr verändert (wird man wohl kaum), dann kann man es in var rein moven (muss man aber selber machen, also
Code:
var = std::move(text);
). Damit hätte man dann bei einem rvalue Parameter 2 moves und bei einem lvalue parameter 1 copy und 1 move. Bei
Code:
var = text;
hätte man bei einem rvalue parameter 1 move und 1 copy und bei einem lvalue parameter 2x copy.

Quote:
Originally Posted by Daifoku View Post
void foo(std::string text);
erstellt eine Kopie und ordnet diese var zu.
var und text werden nicht verändert -> Ressourcen Verschwendung, eine überflüssige Kopie.
Var wird verändert.
Quote:
Originally Posted by Daifoku View Post
void foo(const std::string &text);
erstellt keine Kopie sondern übergibt eine const Referenz.
var = text ist eine legitime Zuweisung, sofern var vom Typ const std::string ist.
Du veränderst var und text nicht, daher ist dies der richtige Ansatz.
var = text ist auch eine legitime Zuweisung, auch wenn var vom typ std::string ist. Warum sollte man ein konstantes Objekt nicht kopieren können ?
th0rex is offline  
Thanks
1 User
Old 10/09/2015, 17:13   #5
 
elite*gold: 0
Join Date: Feb 2009
Posts: 1,137
Received Thanks: 573
Korrigiert mich wenn ich falsch liege aber für mich sieht das wie folgt aus:
void foo(std::string text)
Kopiert den Übergebenen String, das ist ein Zeiger also SizeOf(Pointer) Bytes werden auf den Stack geschrieben
void foo(const std::string &text)
Kopiert die Referenz auf den String, einen Zeiger auf den String Zeiger, also SizeOf(Pointer) Bytes werden auf den Stack geschrieben

Daher von der Schreiboperation kein Unterschied, Aber der Zugriff auf text bei
void foo(const std::string &text)
erfolgt so: Lese Zeiger vom Stack, Lese Memory von der Adresse gegeben von dem Zeiger vom Stack, Das ist der Zeiger auf den String
bei
void foo(std::string text)
Wird der Zeiger auf den String vom Stack direkt gelesen, also nur eine Leseoperation.

Daher sollte
void foo(std::string text)
In dem Fall String eine Operation weniger ausführen
warfley is offline  
Thanks
1 User
Old 10/09/2015, 17:17   #6
 
elite*gold: 46
Join Date: Oct 2010
Posts: 782
Received Thanks: 525
Quote:
Originally Posted by warfley View Post
Korrigiert mich wenn ich falsch liege aber für mich sieht das wie folgt aus:
void foo(std::string text)
Kopiert den Übergebenen String, das ist ein Zeiger also SizeOf(Pointer) Bytes werden auf den Stack geschrieben
Aber der Copy Konstruktor von std::string kopiert nicht den Pointer, sondern wirklich den ganzen String char für char (). Und du hast mehr über den Zugriff auf den string gesprochen. Der Themenersteller möchte aber eher wissen, wie er den String am effizientesten übergeben kann, wenn er ihn kopiert.
th0rex is offline  
Thanks
1 User
Old 10/09/2015, 17:46   #7
 
_Roman_'s Avatar
 
elite*gold: 0
Join Date: May 2010
Posts: 1,620
Received Thanks: 237
Quote:
Originally Posted by C0untLizzi View Post
Aber der Copy Konstruktor von std::string kopiert nicht den Pointer, sondern wirklich den ganzen String char für char (). Und du hast mehr über den Zugriff auf den string gesprochen. Der Themenersteller möchte aber eher wissen, wie er den String am effizientesten übergeben kann, wenn er ihn kopiert.
Genau, quasi was zu den "best practices" gehört. Vielleicht steigere ich mich auch zu sehr da rein, da mein Projekt nicht so schnell wie möglich sein muss.

Quote:
Originally Posted by C0untLizzi View Post
Nein das darf der Compiler nicht. Wenn dann wird der Move Konstruktor vom Argument (also von text) aufgerufen. Da man aber in der Funktion alleinigen Zugriff auf das Objekt text hat und wenn man es in der Funktion nicht mehr verändert (wird man wohl kaum), dann kann man es in var rein moven (muss man aber selber machen, also
Code:
var = std::move(text);
). Damit hätte man dann bei einem rvalue Parameter 2 moves und bei einem lvalue parameter 1 copy und 1 move. Bei
Code:
var = text;
hätte man bei einem rvalue parameter 1 move und 1 copy und bei einem lvalue parameter 2x copy.


Var wird verändert.

var = text ist auch eine legitime Zuweisung, auch wenn var vom typ std::string ist. Warum sollte man ein konstantes Objekt nicht kopieren können ?
Ist dann der const reference Parameter nicht besser, wenn er nur eine Kopie macht?
_Roman_ is offline  
Old 10/09/2015, 17:54   #8
 
elite*gold: 8
Join Date: Sep 2014
Posts: 625
Received Thanks: 178
^ Ja
qqdev is offline  
Old 10/09/2015, 18:13   #9
 
elite*gold: 46
Join Date: Oct 2010
Posts: 782
Received Thanks: 525
Quote:
Originally Posted by _Roman_ View Post
Ist dann der const reference Parameter nicht besser, wenn er nur eine Kopie macht?
Ja. Aber wenn du viele rvalue referenzen übergibst an die Funktion würde es sich lohnen, die Funktion für rvalue referenzen zu überladen. Wenn du by value übergibst, kriegst du für rvalue referenzen "automatisch" schnelleren Code (da std::string sowohl einen Copy Konstruktor, als auch einen Move Konstruktor hat), hast aber immer 1 move mehr. Bei vielen Funktionen, die einen Wert setzen kannst du, wenn du zu Faul bist das immer zu überladen, halt pass by value nehmen, falls du 1 move mehr in Kauf nehmen willst.
th0rex is offline  
Thanks
1 User
Old 10/09/2015, 18:39   #10
 
Padmak's Avatar
 
elite*gold: 58
Join Date: Jun 2008
Posts: 2,311
Received Thanks: 8,420
Quote:
Originally Posted by C0untLizzi View Post
Nein das darf der Compiler nicht. Wenn dann wird der Move Konstruktor vom Argument (also von text) aufgerufen. Da man aber in der Funktion alleinigen Zugriff auf das Objekt text hat und wenn man es in der Funktion nicht mehr verändert (wird man wohl kaum), dann kann man es in var rein moven
Ja okay, es war eher gemeint, dass so dem Compiler Tür und Tor offen stehen für Optimierungen, und dass man selbst auch moven

Die Art der Übergabe ist eigentlich eher davon abhängig, wie du den Parameter weiter verwenden möchtest (Ja, bei manchen Variablen ist es sinnvoll, sich diesbezüglich Gedanken zu machen. Ob du aber einen String mit 20 Buchstaben kopierst, movst oder sonst irgendwie abspeicherst, sollte die Performance nicht nennenswert beeinträchtigen. Außerdem: Grundsätzlich nicht zu viel selbst optimieren, meistens macht mans damit dem Compiler eher schwerer)

Grundsätzlich würde ich es so einordnen:
Wenn du eine noncopyable-Variable in eine Funktion übergeben möchtest, und sie dabei den Inhaber wechselt: by Value, und von außen reinmoven (Siehe den aktuellen std::unique_ptr-Thread)

Einfach nur eine (non-POD) Variable an eine Funktion übergeben: const ref

Zum bearbeiten an eine Funktion übergeben: normale ref

Rest: Value

Generell: Mach dir nicht so übertrieben viele Gedanken um jeden möglichen Kopiervorgang, darüber kannst du dir noch Gedanken machen, wenn dein Programm viel zu langsam läuft und du durch Profiling herausgefunden hast, dass eine spezielle Stelle daran schuld ist

Padmak
Padmak is offline  
Thanks
1 User
Old 10/09/2015, 18:59   #11
 
_Roman_'s Avatar
 
elite*gold: 0
Join Date: May 2010
Posts: 1,620
Received Thanks: 237
Hab mir schon gedacht, dass ich mir da viel zu viele Gedanken mache, zumal Performance nicht mal eine Notwendigkeit ist bei dem Projekt.

Quote:
Originally Posted by Padmak View Post
Grundsätzlich würde ich es so einordnen:
Wenn du eine noncopyable-Variable in eine Funktion übergeben möchtest, und sie dabei den Inhaber wechselt: by Value, und von außen reinmoven (Siehe den aktuellen std::unique_ptr-Thread)

Einfach nur eine (non-POD) Variable an eine Funktion übergeben: const ref
Die beiden Teile verstehe ich nicht so ganz. Wo ist der Zusammenhang von diesem Thread mit den std::unique_ptr und was sind non-POD Variablen genau? Hab da kurz was zu gelesen, aber das hab ich nicht verstanden.

Ich kann ja mal beschreiben, auf welchen Code ich die Lösung dann anwenden möchte. Also ich verwende Qt und hab da ein Signal, welches als Parameter const QString& hat. Das Signal wird ausgelöst, wenn man ein Textfeld verlässt, also enthält der Parameter den Text. Nun will ich wissen, was der geeignetste Parameter für meine Slot Funktion ist, die quasi wie oben erwähnt aussieht. Ich habe da einfach nur eine Zuweisung drin. Ich nehme mal an, dass der const QString& Parameter vom Signal direkt als Argument für meine Slot Funktion verwendet wird.

Meinst du das mit Inhaber wechseln? Wäre dann also

Code:
void foo(std::string text)
{
     var = std::move(text);
}
am Besten oder hab ich deine Einordnung falsch verstanden?
_Roman_ is offline  
Old 10/09/2015, 19:26   #12
 
elite*gold: 46
Join Date: Oct 2010
Posts: 782
Received Thanks: 525
Quote:
Originally Posted by Padmak View Post
Außerdem: Grundsätzlich nicht zu viel selbst optimieren, meistens macht mans damit dem Compiler eher schwerer
Ich würde überladen für rvalue Referenzen oder manuell std::move zu nutzen jetzt als eine große Optimierung bezeichnen. Der Compiler darf etwas wie
Code:
std::string myStr = "";
myFunc(myStr);
einfach nicht moven und man sollte ihm schon "sagen" (mit std::move), dass myStr nicht mehr genutzt wird und der Compiler das moven darf. Wobei std::move halt eben auch nicht immer automatisch etwas movet. Wenn die Funktion nur const T& nimmt, dann wird da nichts gemovet, sondern das temporäre Objekt wird an die Referenz gebunden. Da kann dann ein Compiler auch nicht einfach eine Funktion mit einer rvalue Signatur generieren, sondern diese muss man selber schreiben. Aber generell hast du recht. Nur etwas wie temporäre Objekte kommt halt doch schon häufiger vor und deswegen kann man dafür auch manuell optimieren.

Quote:
Originally Posted by _Roman_ View Post
Wäre dann also
Code:
void foo(std::string text)
{
     var = std::move(text);
}
am Besten oder hab ich deine Einordnung falsch verstanden?
Wenn du nicht weiß, wie der Parameter übergeben wird, dann ja. Falls ein lvalue Parameter übergeben wird, verlangsamst du im Vergleich zu der Variante mit der konstanten Referenz deine Funktion zwar um diese move Zuweisung. Aber falls ein rvalue Parameter übergeben wird, hast du 2 mal ein move, anstatt einmal copy (edit: Ich möchte hier nochmal sagen, dass Padmak mit kleinen strings schon recht hat. Bei < 16 Zeichen kannst du ruhig dieses 1 copy in Kauf nehmen, anstatt dass du 2mal ein move hast. Move ist auch nicht kostenlos. Aber wenn es z.B. um einen vector geht mit vllt mehreren 100 Elementen solltest du den auf jeden Fall nicht unnötig kopieren.)

Wenn du weißt, dass da ein lvalue übergeben wird, dann nimm die Variante mit der konstanten Referenz. Dann hast du nur 1 copy.
Wenn du weißt, dass da ein rvalue übergeben wird, dann nimm die Variante mit der rvalue Referenz und mach halt var = std::move(arg). Dann hast du nur 1 move.
th0rex is offline  
Thanks
1 User
Old 10/09/2015, 23:56   #13
 
Padmak's Avatar
 
elite*gold: 58
Join Date: Jun 2008
Posts: 2,311
Received Thanks: 8,420
Kannst du kurz ein Beispiel zeigen, was du mit "überladen für rvalue Referenzen" in diesem Fall genau meinst?

Non-POD Datentypen sind einfach Datentypen, die komplexer sind (= nicht trivial kopierbar) sind als POD (Plain Old Data) - Typen

Äh.. Wenn du QT benutzt, dann läuft das ganze sowieso ein bisschen anders, soweit ich nach kurzer Google-Suche gefunden habe
Schau dir hier mal die akzeptierte Antwort an:

Anscheinend kopiert Qt intern unabhängig davon was du haben möchtest, wenn bestimmte Voraussetzungen erfüllt/nicht erfüllt sind

Edit:
Vor allem bei solchen Sachen wie Strings ist es mir schon länger relativ egal, ob die jetzt ein mal mehr oder weniger kopiert werden - Die meisten meiner Programme haben immer relativ deutliche Bottlenecks, so wie IO oder sonstige Benutzereingaben, da ist es bisher noch nie an zu vielen temporären Kopien von irgendwas gescheitert

Padmak
Padmak is offline  
Thanks
1 User
Old 10/10/2015, 10:45   #14
 
elite*gold: 46
Join Date: Oct 2010
Posts: 782
Received Thanks: 525
Quote:
Originally Posted by Padmak View Post
Kannst du kurz ein Beispiel zeigen, was du mit "überladen für rvalue Referenzen" in diesem Fall genau meinst?
Sagen wir, wir haben so eine Funktion:
Code:
void myFunc(const std::string& arg){
     val = arg;
}
Damit haben wird ja einmal arg kopiert.
Wenn wir jetzt noch eine 2. Funktion haben:
Code:
std::string getString(){ /*von irgendwo wird hier ein string zurück gegeben*/}
Und oft die 1. Funktion so aufrufen:
Code:
myFunc(getString());
Dann ist der typ von dem Parameter eigentlich std::string&&. Da wir die Funktion aber nur ein const std::string& annehmen lassen, wird diese Variante aufgerufen und wir bekommen keinen Vorteil dadurch, dass der Parameter eine rvalue Referenz eigentlich ist. Wenn wir die Funktion jetzt so überladen:
Code:
void myFunc(std::string&& arg)
{
     var = std::move(arg);
}
Nutzen wir halt diesen Fall aus und kopieren den String nicht. Und wenn es häufig vorkommt, dass man rvalue Referenzen übergibt lohnt es sich schon die Funktion für diese zu überladen. Noch ein Beispiel bei dem eine rvalue Referenzen übergeben wird, was häufig vorkommen kann:
Code:
someFunc(arg1 + arg2); // 1.
Wenn jetzt arg1 und arg2 nicht grade integer (oder Zahlen an sich sind) könnte das kopieren dann doch schon langsamer sein, als std::move zu nutzen, z.B. wenn arg1 und arg2 strings sind.

Quote:
Originally Posted by Padmak View Post
Edit:
Vor allem bei solchen Sachen wie Strings ist es mir schon länger relativ egal, ob die jetzt ein mal mehr oder weniger kopiert werden - Die meisten meiner Programme haben immer relativ deutliche Bottlenecks, so wie IO oder sonstige Benutzereingaben, da ist es bisher noch nie an zu vielen temporären Kopien von irgendwas gescheitert
Ja bei den meisten Strings ist das nicht wichtig. Aber es kann halt sein, dass man von irgendeinem Datei Format lange Zeilen einliest und dann ungefähr sowas hat:
Code:
myFunc(readNextLine());
Und wenn das wirklich lange Zeilen sind, dann kann man das schon merken (vor allem, wenn das in ner Loop aufgerufen wird). Edit: Wobei ich hier wohl auch sagen muss, dass man readNextLine besser so deklarieren sollte:
Code:
void readNextLine(std::string& out);
Code:
std::string l;
while(true)
    readNextLine(l);
Wenn die 1. Zeile 1000 Zeichen hat und die 2. 500, muss da nichts mehr allokiert werden. Bei der ersten Variante wird da für jede Zeile Speicher allokiert.

Aber für kleine Strings hast du definitiv recht. Bei weniger als 12 Zeichen pro String kann ein move sogar länger als ein copy dauern, da bei so kurzen strings etwas namens small string optimization angewandt wird, bei dem kein Speicher für den string allokiert wird, sondern interne Variablen vom std::string dafür genutzt werden. std::string hat normal 3 Variablen: die Länge, die Größe des allokierten Speichers und einen pointer auf diesen Speicher. Bei 32 bit sind das 12 bytes. Wenn man jetzt nur 11 Zeichen hat, dann darf die standard library diese 11 Zeichen direkt in den Variablen speichern. Das heißt, dass das 1. Byte der Länge dann wirklich die Länge speichert, die letzten 3 aber die 1. 3 Zeichen des strings. Auch in die anderen 2 Variablen darf die Klasse dann jeweils 4 Zeichen speichern, womit man dann bei insgesamt 11 Zeichen wäre, ohne extra Speicher für diese zu allokieren. Dann kann ein move von diesem String langsamer als ein copy sein. Ein "normaler" move von einem String ist generell schneller, weil da kein Speicher allokiert werden muss (und der string sich den pointer einfach klaut). Aber wenn sowieso kein Speicher allokiert werden muss, dann sind sowohl ein copy, als auch ein move, 3mal das kopieren von 4 bytes. Wobei es beim move noch sein kann, dass es die Variablen von dem String, von dem Sachen genommen werden, auf einen default Wert setzen muss. Dabei bin ich mir aber nicht sicher und ich weiß nur, dass das Objekt, von dem gemovt wird, in einem "valid state" sein muss (was es ja wäre, selbst wenn nichts auf einen default Wert gesetzt wird. Deswegen ist es unwahrscheinlich, dass es wirklich langsamer ist, aber eine Implementation dürfte es langsamer machen).

tl;dr: Bei < 11 Zeichen KÖNNTE (Implementations abhängig und unwahrscheinlich) es sein, dass ein move länger dauert als ein copy für einen std::string. Also hast du schon recht, dass man mit dem Optimieren nicht übertreiben sollte, aber manchmal kann etwas so triviales wie "Lieber std::string returnen oder über Referenz nach außen übergeben?" schon einen großen Unterschied machen.

Nebenbei: QString und std::string sind afaik schon sehr underschiedlich und nichts, was ich hier über std::string sage muss auf QString zutreffen.
th0rex is offline  
Thanks
1 User
Old 10/10/2015, 11:50   #15
 
_Roman_'s Avatar
 
elite*gold: 0
Join Date: May 2010
Posts: 1,620
Received Thanks: 237
Quote:
Originally Posted by Padmak View Post
Äh.. Wenn du QT benutzt, dann läuft das ganze sowieso ein bisschen anders, soweit ich nach kurzer Google-Suche gefunden habe
Schau dir hier mal die akzeptierte Antwort an:

Anscheinend kopiert Qt intern unabhängig davon was du haben möchtest, wenn bestimmte Voraussetzungen erfüllt/nicht erfüllt sind
Heißt das also, dass ich mit std::move und nem normalen QString Parameter arbeiten sollte, wenn Qt den String kopiert? Verlier grad etwas den Überblick bei den ganzen Informationen
_Roman_ is offline  
Reply


Similar Threads Similar Threads
Is there a packet reference available
04/24/2012 - CO2 Private Server - 14 Replies
Hello everyone, I might start working on a private server in Java after my finals are over so I have question to ask you guys. Is there any packet reference guide like Korvacs wiki still available for me to use? I know that I can simply download some of the public sources to get the structures and use that but I would just like to know if one still exists. Thanks, Tkblackbelt
Looking for a reference
11/08/2011 - Dekaron Private Server - 8 Replies
We are sorry but we just got this letter and we comply with the msg " To Elitepvpers The account Cataracts - Daemon Strother has been reported for multiple crimes by the US state department of illegal Child sexual abuse! law § 2243 - Sexual abuse of a minor or ward: (a) Of a Minor.— Whoever, in the special maritime and territorial jurisdiction of the United States or in a Federal prison, or in any prison, institution, or facility in which persons are held in custody by direction of or...
[S] 3€ handyguthaben [B] 3Day Pass + 3 Promo Codes oder 10Day Pass
06/02/2011 - WarRock Trading - 1 Replies
Heai Epvpers. Ich Suche jemanden der seine Handykarte zur verfügung stellt. Es müssen mindestens 3€ auf der karte vorhanden sein. Es würde so Funktionieren , ihr sagt mir eure Handynummer dann geb ich sie auf einer seite ein und ihr beckommt einen Code per sms zugesendet , diesen Code sagt ihr mir dann. Nachdem ich diesen Code Abgegeben habe beckommt ihr mehrere SMS und euch werden 3€ vom Guthaben abgebucht. Nach dem das geschehen ist habe ich auf einem Konto von einer Anderen Seite ein...
My Reference For Cheats
02/23/2011 - Facebook - 0 Replies
The Website Which Gives/Shares To Me New,Fresh,100% Working Cheats Is facebookgamestricks.tk Visit The Page And See More Cheats Up Everyday There Are 5 Cheats Fresh Please Cooperate
just a reference
11/26/2008 - Dekaron Exploits, Hacks, Bots, Tools & Macros - 0 Replies
havnt been on for some time i dont know if its any help at all this is an old sheet i used to use to find things quicker with winhex though id post it :) If someone else has posted it im sorry in advance :handsdown: the way i use it is simple just say i wanted to find a Great mana potion all i would do is click the search tab in winhex then find text then enter 3806 then it should be the first item that pops up with a line that looks like 3806,Great Mana...



All times are GMT +1. The time now is 05:47.


Powered by vBulletin®
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2026 elitepvpers All Rights Reserved.