<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Codequalität]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich programmiere im Rahmen zweier Vorlesungen nun seid etwa 3 Monaten C(++). Genug Zeit um sich in eine Sprache einzuarbeiten, jedoch noch viel zu wenig um alle Details zu kennen.</p>
<p>Mich würde es nun mal interessieren, was ihr meint, was ich noch so an meinem Code verbessern könnte. Als Beispiel nehme ich hier einfach mal den Code, den ich für unsere aktuelle Übung geschrieben habe (Vektorklasse ohne Speicherung leerer Felder).</p>
<p>Konkret würde mich beispielsweise interessieren, ob es überhaupt Sinn macht kleine Funktionen wie get... und set... als inline zu deklarieren, oder ob das durch Compileroptimierung heute eh egal ist und ob man die +- und -Operatoren nicht irgendwie noch zusammen fassen kann um den redundanten Code zu vermeiden (ich dachte z.B. an eine Funktion, der man einen Operator (+/-) als Parameter übergibt, habe das allerdings nicht hinbekommen). Allerdings freue ich mich auch über alle weiteren Anmerkungen zum Code.</p>
<p>Hier nun der Quelltest (SparseVector.hpp):</p>
<pre><code class="language-cpp">#ifndef SPARSEVEKTOR_HPP_INCLUDED
#define SPARSEVEKTOR_HPP_INCLUDED

#include &lt;stdexcept&gt;

using std::invalid_argument;
using std::out_of_range;

// A linked-list node for our sparse vector elements.
template &lt;class T&gt; class Node {
	public:
		// Node constructor - simply initializes the data-members.
		Node(int idx, T val, Node *nxt)
		: index(idx), value(val), next(nxt) {}

		Node()
		: index(-1), next(NULL) {}

		inline int getIndex() const {
			return index;
		}

		inline void setIndex(const int idx) {
			index = idx;
		}

		inline Node * getNext() const {
			return next;
		}

		inline void setNext(Node&lt;T&gt; * nextNode) {
			next = nextNode;
		}

		inline T getValue() const {
			return value;
		}

		inline void setValue(const T val) {
			value = val;
		}

		bool operator == (const Node&lt;T&gt; &amp; n) const {
			return (index == n.index) &amp;&amp; (value == n.value);
		}

		bool operator != (const Node&lt;T&gt; &amp; n) const {
			return !(*this == n);
		}

	private:
		int index; // Element number, in the range [0, size)
		T value; // The value of this element.
		Node *next; // A pointer to the next node in the linked-list.
};

template &lt;class T&gt; class SparseVector {
	public:
		SparseVector(const int size = 1)
		: size(size), elements(new Node&lt;T&gt;()) {
			if (size &lt;= 0)
				throw new invalid_argument(&quot;Argument must be greater than zero!&quot;);
		};

		SparseVector(const SparseVector&lt;T&gt; &amp; spvc)
		: size(spvc.size), elements(new Node&lt;T&gt;()) {
			*this = spvc;
		};

		~SparseVector() {
			Node&lt;T&gt; * aktElem = elements;
			while (aktElem) {
				Node&lt;T&gt; * nextElem = aktElem-&gt;getNext();
				delete aktElem;
				aktElem = nextElem;
			}
		};

		void print(std::ostream &amp; out, const std::string seperator) {
			for (int i = 0; i &lt; size; i++) {
				out &lt;&lt; getElement(i) &lt;&lt; seperator;
			}
		}

		T getElement(const int col) const {
			if ((col &lt; 0) || (col &gt;= size))
				throw new out_of_range(&quot;Not a valid vector element!&quot;);
			Node&lt;T&gt; * elem = elements;
			while ((elem) &amp;&amp; (elem-&gt;getIndex() &lt; col))
				elem = elem-&gt;getNext();
			if (elem &amp;&amp; (elem-&gt;getIndex() == col))
				return elem-&gt;getValue();
			return 0;
		};

		void setElement(const int col, const T value) {
			if ((col &lt; 0) || (col &gt;= size))
				throw new out_of_range(&quot;Not a valid vector element!&quot;);
			Node&lt;T&gt; * lastElem = elements;
			Node&lt;T&gt; * aktElem = elements-&gt;getNext();
			while ((aktElem) &amp;&amp; (aktElem-&gt;getIndex() &lt; col)) {
				lastElem = aktElem;
				aktElem = aktElem-&gt;getNext();
			}
			if (!aktElem || (aktElem-&gt;getIndex() != col)) {
				if (value != 0)
					lastElem-&gt;setNext(new Node&lt;T&gt;(col, value, aktElem));
			} else if (value == 0) {
				lastElem-&gt;setNext(aktElem-&gt;getNext());
				delete aktElem;
			} else {
				aktElem-&gt;setValue(value);
			}
		};

		inline int getSize() {
			return size;
		};

		SparseVector &amp; operator = (const SparseVector &amp; spvc) {
			if (this == &amp;spvc)
				return *this;
			size = spvc.size;

			Node&lt;T&gt; * aktElem = elements;
			Node&lt;T&gt; * newElem = spvc.elements-&gt;getNext();

			while (aktElem-&gt;getNext() &amp;&amp; newElem) {
				aktElem = aktElem-&gt;getNext();
				aktElem-&gt;setIndex(newElem-&gt;getIndex());
				aktElem-&gt;setValue(newElem-&gt;getValue());
				newElem = newElem-&gt;getNext();
			}
			if (newElem) {
				while (newElem) {
					aktElem-&gt;setNext(new Node&lt;T&gt;(*newElem));
					newElem = newElem-&gt;getNext();
					aktElem = aktElem-&gt;getNext();
				}
			} else {
				aktElem = aktElem-&gt;getNext();
				while (aktElem) {
					Node&lt;T&gt; * nextElem = aktElem-&gt;getNext();
					delete aktElem;
					aktElem = nextElem;
				}
			}
			return *this;
		}

		bool operator == (const SparseVector &amp; spvc) const {
			if (spvc.size != size)
				return false;
			Node&lt;T&gt; * aElem = elements-&gt;getNext();
			Node&lt;T&gt; * bElem = spvc.elements-&gt;getNext();
			while (aElem &amp;&amp; bElem &amp;&amp; (*aElem == *bElem)) {
				aElem = aElem-&gt;getNext();
				bElem = bElem-&gt;getNext();
			}
			return !aElem &amp;&amp; !bElem;
		}

		bool operator != (const SparseVector &amp; spvc) const {
			return !(*this == spvc);
		}

		SparseVector operator + (const SparseVector &amp; spvc) const {
			if (size != spvc.size)
				throw new invalid_argument(&quot;Dimension must be the same!&quot;);

			SparseVector result(size);
			for (int i = 0; i &lt; size; i++) {
				result.setElement(i, getElement(i) + spvc.getElement(i));
			}
			return result;
		}

		SparseVector operator - (const SparseVector &amp; spvc) const {
			if (size != spvc.size)
				throw new invalid_argument(&quot;Dimension must be the same!&quot;);

			SparseVector result(size);
			for (int i = 0; i &lt; size; i++) {
				result.setElement(i, getElement(i) - spvc.getElement(i));
			}
			return result;
		}

		SparseVector &amp; operator += (const SparseVector &amp; spvc) {
			*this = *this + spvc;
			return *this;
		}

		SparseVector &amp; operator -= (const SparseVector &amp; spvc) {
			*this = *this - spvc;
			return *this;
		}
	private:
		int size;
		Node&lt;T&gt; * elements;
};

#endif // SPARSEVEKTOR_HPP_INCLUDED
</code></pre>
<p>Gruß Lars</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/231470/codequalität</link><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 20:39:54 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/231470.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 11 Jan 2009 12:33:18 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 12:36:38 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich programmiere im Rahmen zweier Vorlesungen nun seid etwa 3 Monaten C(++). Genug Zeit um sich in eine Sprache einzuarbeiten, jedoch noch viel zu wenig um alle Details zu kennen.</p>
<p>Mich würde es nun mal interessieren, was ihr meint, was ich noch so an meinem Code verbessern könnte. Als Beispiel nehme ich hier einfach mal den Code, den ich für unsere aktuelle Übung geschrieben habe (Vektorklasse ohne Speicherung leerer Felder).</p>
<p>Konkret würde mich beispielsweise interessieren, ob es überhaupt Sinn macht kleine Funktionen wie get... und set... als inline zu deklarieren, oder ob das durch Compileroptimierung heute eh egal ist und ob man die +- und -Operatoren nicht irgendwie noch zusammen fassen kann um den redundanten Code zu vermeiden (ich dachte z.B. an eine Funktion, der man einen Operator (+/-) als Parameter übergibt, habe das allerdings nicht hinbekommen). Allerdings freue ich mich auch über alle weiteren Anmerkungen zum Code.</p>
<p>Hier nun der Quelltest (SparseVector.hpp):</p>
<pre><code class="language-cpp">#ifndef SPARSEVEKTOR_HPP_INCLUDED
#define SPARSEVEKTOR_HPP_INCLUDED

#include &lt;stdexcept&gt;

using std::invalid_argument;
using std::out_of_range;

// A linked-list node for our sparse vector elements.
template &lt;class T&gt; class Node {
	public:
		// Node constructor - simply initializes the data-members.
		Node(int idx, T val, Node *nxt)
		: index(idx), value(val), next(nxt) {}

		Node()
		: index(-1), next(NULL) {}

		inline int getIndex() const {
			return index;
		}

		inline void setIndex(const int idx) {
			index = idx;
		}

		inline Node * getNext() const {
			return next;
		}

		inline void setNext(Node&lt;T&gt; * nextNode) {
			next = nextNode;
		}

		inline T getValue() const {
			return value;
		}

		inline void setValue(const T val) {
			value = val;
		}

		bool operator == (const Node&lt;T&gt; &amp; n) const {
			return (index == n.index) &amp;&amp; (value == n.value);
		}

		bool operator != (const Node&lt;T&gt; &amp; n) const {
			return !(*this == n);
		}

	private:
		int index; // Element number, in the range [0, size)
		T value; // The value of this element.
		Node *next; // A pointer to the next node in the linked-list.
};

template &lt;class T&gt; class SparseVector {
	public:
		SparseVector(const int size = 1)
		: size(size), elements(new Node&lt;T&gt;()) {
			if (size &lt;= 0)
				throw new invalid_argument(&quot;Argument must be greater than zero!&quot;);
		};

		SparseVector(const SparseVector&lt;T&gt; &amp; spvc)
		: size(spvc.size), elements(new Node&lt;T&gt;()) {
			*this = spvc;
		};

		~SparseVector() {
			Node&lt;T&gt; * aktElem = elements;
			while (aktElem) {
				Node&lt;T&gt; * nextElem = aktElem-&gt;getNext();
				delete aktElem;
				aktElem = nextElem;
			}
		};

		void print(std::ostream &amp; out, const std::string seperator) {
			for (int i = 0; i &lt; size; i++) {
				out &lt;&lt; getElement(i) &lt;&lt; seperator;
			}
		}

		T getElement(const int col) const {
			if ((col &lt; 0) || (col &gt;= size))
				throw new out_of_range(&quot;Not a valid vector element!&quot;);
			Node&lt;T&gt; * elem = elements;
			while ((elem) &amp;&amp; (elem-&gt;getIndex() &lt; col))
				elem = elem-&gt;getNext();
			if (elem &amp;&amp; (elem-&gt;getIndex() == col))
				return elem-&gt;getValue();
			return 0;
		};

		void setElement(const int col, const T value) {
			if ((col &lt; 0) || (col &gt;= size))
				throw new out_of_range(&quot;Not a valid vector element!&quot;);
			Node&lt;T&gt; * lastElem = elements;
			Node&lt;T&gt; * aktElem = elements-&gt;getNext();
			while ((aktElem) &amp;&amp; (aktElem-&gt;getIndex() &lt; col)) {
				lastElem = aktElem;
				aktElem = aktElem-&gt;getNext();
			}
			if (!aktElem || (aktElem-&gt;getIndex() != col)) {
				if (value != 0)
					lastElem-&gt;setNext(new Node&lt;T&gt;(col, value, aktElem));
			} else if (value == 0) {
				lastElem-&gt;setNext(aktElem-&gt;getNext());
				delete aktElem;
			} else {
				aktElem-&gt;setValue(value);
			}
		};

		inline int getSize() {
			return size;
		};

		SparseVector &amp; operator = (const SparseVector &amp; spvc) {
			if (this == &amp;spvc)
				return *this;
			size = spvc.size;

			Node&lt;T&gt; * aktElem = elements;
			Node&lt;T&gt; * newElem = spvc.elements-&gt;getNext();

			while (aktElem-&gt;getNext() &amp;&amp; newElem) {
				aktElem = aktElem-&gt;getNext();
				aktElem-&gt;setIndex(newElem-&gt;getIndex());
				aktElem-&gt;setValue(newElem-&gt;getValue());
				newElem = newElem-&gt;getNext();
			}
			if (newElem) {
				while (newElem) {
					aktElem-&gt;setNext(new Node&lt;T&gt;(*newElem));
					newElem = newElem-&gt;getNext();
					aktElem = aktElem-&gt;getNext();
				}
			} else {
				aktElem = aktElem-&gt;getNext();
				while (aktElem) {
					Node&lt;T&gt; * nextElem = aktElem-&gt;getNext();
					delete aktElem;
					aktElem = nextElem;
				}
			}
			return *this;
		}

		bool operator == (const SparseVector &amp; spvc) const {
			if (spvc.size != size)
				return false;
			Node&lt;T&gt; * aElem = elements-&gt;getNext();
			Node&lt;T&gt; * bElem = spvc.elements-&gt;getNext();
			while (aElem &amp;&amp; bElem &amp;&amp; (*aElem == *bElem)) {
				aElem = aElem-&gt;getNext();
				bElem = bElem-&gt;getNext();
			}
			return !aElem &amp;&amp; !bElem;
		}

		bool operator != (const SparseVector &amp; spvc) const {
			return !(*this == spvc);
		}

		SparseVector operator + (const SparseVector &amp; spvc) const {
			if (size != spvc.size)
				throw new invalid_argument(&quot;Dimension must be the same!&quot;);

			SparseVector result(size);
			for (int i = 0; i &lt; size; i++) {
				result.setElement(i, getElement(i) + spvc.getElement(i));
			}
			return result;
		}

		SparseVector operator - (const SparseVector &amp; spvc) const {
			if (size != spvc.size)
				throw new invalid_argument(&quot;Dimension must be the same!&quot;);

			SparseVector result(size);
			for (int i = 0; i &lt; size; i++) {
				result.setElement(i, getElement(i) - spvc.getElement(i));
			}
			return result;
		}

		SparseVector &amp; operator += (const SparseVector &amp; spvc) {
			*this = *this + spvc;
			return *this;
		}

		SparseVector &amp; operator -= (const SparseVector &amp; spvc) {
			*this = *this - spvc;
			return *this;
		}
	private:
		int size;
		Node&lt;T&gt; * elements;
};

#endif // SPARSEVEKTOR_HPP_INCLUDED
</code></pre>
<p>Gruß Lars</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643314</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643314</guid><dc:creator><![CDATA[Hador_]]></dc:creator><pubDate>Sun, 11 Jan 2009 12:36:38 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:01:44 GMT]]></title><description><![CDATA[<p>ich würde auch auf seltenes globales using im header verzichten.<br />
und }; am funktionsende ist falsch.<br />
die leere anweisung ; darf im code nach blöcken stehen, es gibt aber keine leere deklaration, glaub ich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643328</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643328</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:01:44 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:03:47 GMT]]></title><description><![CDATA[<p>du hast vorher java gelernt, stimmts?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643329</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643329</guid><dc:creator><![CDATA[kaffeeerkenner]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:03:47 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:06:47 GMT]]></title><description><![CDATA[<p>Tag auch,</p>
<p>also zum Thema Codequalität: Das meiste gefällt zumindest mir, allerdings bin ich eher ein Verfechter dieses Stils:</p>
<pre><code class="language-cpp">int blub(bool xyz)
{
    xyz = false;
    return -1;
}
</code></pre>
<p>Das ist allerdings Geschmackssache und bleibt dir überlassen.<br />
Was ich dir allerdings dringenst empfehle: Teile deine Deklarationen und Definitionen auf zwei Files, also *.h und *.cpp auf.</p>
<blockquote>
<p>Konkret würde mich beispielsweise interessieren, ob es überhaupt Sinn macht kleine Funktionen wie get... und set... als inline zu deklarieren, oder ob das durch Compileroptimierung heute eh egal ist und ob man die +- und -Operatoren nicht irgendwie noch zusammen fassen kann um den redundanten Code zu vermeiden (ich dachte z.B. an eine Funktion, der man einen Operator (+/-) als Parameter übergibt, habe das allerdings nicht hinbekommen). Allerdings freue ich mich auch über alle weiteren Anmerkungen zum Code.</p>
</blockquote>
<p>Afaik werden solche Methoden eh entsprechend optimiert aber lass das inline doch einfach stehen, es stört ja nicht :).</p>
<p>Zum Stichwort Operator als Parameter, kuck dir doch mal an wie dass bei accumulate gelöst wurde:<br />
<a href="http://www.cplusplus.com/reference/std/numeric/accumulate.html" rel="nofollow">http://www.cplusplus.com/reference/std/numeric/accumulate.html</a></p>
<p>Ich an deiner Stelle würde die Operatoren jedoch so lassen wie sie sind, eine meiner Meinung nach sinnvolle Optimierung ist da nichtmehr möglich.</p>
<p>Hoffe ich konnte helfen,</p>
<p>Max</p>
<p>#edit: Wegen dem ; nach der Funktionsdeklaration, Afaik ist das so legitim allerdings würde ich den Strichpunkt grundsätzlich weglassen. Wenn du ihn möchteste dann mach ihn hinter alle Funktionsdeklarationen und nicht nur hinter manche.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643330</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643330</guid><dc:creator><![CDATA[blub* 0]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:06:47 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:04:55 GMT]]></title><description><![CDATA[<p>wohl besser, du implementiertst den copy-ctor normal und dern op= mit copy&amp;swap?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643331</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643331</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:04:55 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:06:37 GMT]]></title><description><![CDATA[<p>blub² schrieb:</p>
<blockquote>
<p>Was ich dir allerdings dringenst empfehle: Teile deine Deklarationen und Definitionen auf zwei Files, also *.h und *.cpp auf.</p>
</blockquote>
<p>nee nee nee<br />
ist doch ein template. das bleibt brav im header leben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643334</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643334</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:06:37 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:09:46 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>blub² schrieb:</p>
<blockquote>
<p>Was ich dir allerdings dringenst empfehle: Teile deine Deklarationen und Definitionen auf zwei Files, also *.h und *.cpp auf.</p>
</blockquote>
<p>nee nee nee<br />
ist doch ein template. das bleibt brav im header leben.</p>
</blockquote>
<p>Hmm... vlt. sollte ich nicht über Sachen schreiben von denen ich nicht allzuviel Ahnung habe :S. Also bleiben bei Template Klassen grundsätzlich Deklarationen und Definitionen im Header vereint?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643344</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643344</guid><dc:creator><![CDATA[blub* 0]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:09:46 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:21:53 GMT]]></title><description><![CDATA[<p>Auch bei Templates kann man Deklaration und Implementierung trennen. Man inkludiert einfach die implementierten Methoden nach der Klassendeklaration.</p>
<p>Gruß<br />
Don06</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643353</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643353</guid><dc:creator><![CDATA[Don06]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:21:53 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:44:30 GMT]]></title><description><![CDATA[<p>blub² schrieb:</p>
<blockquote>
<p>Hmm... vlt. sollte ich nicht über Sachen schreiben von denen ich nicht allzuviel Ahnung habe</p>
</blockquote>
<p>das wäre schlimm. dann hätten wir gar nicht drüber reden können, daß bei templates der compiler vor dem benutzen die definition lesen könen muss, weshalb die definition auch irgendwie inkludiert werden muss.</p>
<blockquote>
<p>:S. Also bleiben bei Template Klassen grundsätzlich Deklarationen und Definitionen im Header vereint?</p>
</blockquote>
<p>naja, grundsätzlich nicht. zum einen machen manche leute zwei headers, SparseVector.hpp und SparseVectorImpl.hpp,<br />
zum anderen gibt es da noch (mehr als theoretische möglichkeit) sachen mit extern und templates.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643363</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643363</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:44:30 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:54:42 GMT]]></title><description><![CDATA[<p>Danke schonmal ich glaube ich habs kapiert :P.<br />
Zumindest teilweise:</p>
<blockquote>
<p>naja, grundsätzlich nicht. zum einen machen manche leute zwei headers, SparseVector.hpp und SparseVectorImpl.hpp,<br />
zum anderen gibt es da noch (mehr als theoretische möglichkeit) sachen mit extern und templates.</p>
</blockquote>
<p>Was steht denn hier jeweils drin? Ist mir nicht so ganz klar geworden.</p>
<p>Danke schonmal &amp; Gruss,</p>
<p>Max</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643372</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643372</guid><dc:creator><![CDATA[blub* 0]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:54:42 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 13:58:38 GMT]]></title><description><![CDATA[<p>Zusaetzlich zu dem bereits genannten<br />
Kleiner Tipp:</p>
<pre><code class="language-cpp">SparseVector(const int size = 1) 
        : size(size), elements(new Node&lt;T&gt;()) { 
            if (size &lt;= 0) 
                throw new invalid_argument(&quot;Argument must be greater than zero!&quot;); 
        };
</code></pre>
<p>Wenn du size als unisgned definierst, dann sparst du dir diese Ueberpruefung (und du hast dann auch kein memory leak mehr).</p>
<pre><code class="language-cpp">SparseVector &amp; operator -= (const SparseVector &amp; spvc) {
            *this = *this - spvc;
            return *this;
        }
</code></pre>
<p>Viel besser ist es den operator- mit Hilfe des operator-= zu implementieren.</p>
<p>Im Prinzip aber ganz nett.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643375</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643375</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Sun, 11 Jan 2009 13:58:38 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 16:01:06 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>zum anderen gibt es da noch (mehr als theoretische möglichkeit) sachen mit extern und templates.</p>
</blockquote>
<p>Du meinst wahrscheinlich <code>export</code> ... Soviel ich weiss, unterstützen das aber die wenigsten Compiler, und bei denen, die das Schlüsselwort unterstützen, zahlt es sich nicht wirklich aus.</p>
<p>Vielleicht noch <code>operator+</code> und <code>operator-</code> global machen, und die dann auf die Member <code>+=</code> und <code>-=</code> zugreifen lassen. Wieso wirfst du die Exception eigentlich auf dem Heap? Also</p>
<pre><code class="language-cpp">throw new invalid_argument(&quot;Argument must be greater than zero!&quot;);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1643436</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643436</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 11 Jan 2009 16:01:06 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 16:10:13 GMT]]></title><description><![CDATA[<p>Erst mal danke für die vielen Antworten!</p>
<p>volkard schrieb:</p>
<blockquote>
<p>ich würde auch auf seltenes globales using im header verzichten.</p>
</blockquote>
<p>Werde ich ändern.</p>
<p>volkard schrieb:</p>
<blockquote>
<p>und }; am funktionsende ist falsch.</p>
</blockquote>
<p>Der Compiler frisst es zwar so, aber du hast Recht. Ich hatte zunächst eine ganz normale Header-Datei (ohne Template) geschrieben und da steht ja immer ein ;. beim hinzufügen der Implementierung habe ich dies dann wohl vergessen zu entfernen.</p>
<p>---</p>
<p>kaffeeerkenner schrieb:</p>
<blockquote>
<p>du hast vorher java gelernt, stimmts?</p>
</blockquote>
<p>Jo, ich habe gut ein Jahr lang Java programmieren müssen. Eigentlich komme ich jedoh aus der Object-Pascal-Ecke. Merkt man das Java so sehr?</p>
<p>---</p>
<p>blub² schrieb:</p>
<blockquote>
<p>Zum Stichwort Operator als Parameter, kuck dir doch mal an wie dass bei accumulate gelöst wurde:<br />
<a href="http://www.cplusplus.com/reference/std/numeric/accumulate.html" rel="nofollow">http://www.cplusplus.com/reference/std/numeric/accumulate.html</a></p>
<p>Ich an deiner Stelle würde die Operatoren jedoch so lassen wie sie sind, eine meiner Meinung nach sinnvolle Optimierung ist da nichtmehr möglich.</p>
</blockquote>
<p>Werde ich mir gleich dennoch mal ansehen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";-)"
      alt="😉"
    /></p>
<p>---</p>
<p>volkard schrieb:</p>
<blockquote>
<p>wohl besser, du implementiertst den copy-ctor normal und dern op= mit copy&amp;swap?</p>
</blockquote>
<p>Aber im op= muss doch nicht immer jedes Element neu erzeugt werden, im cp-ctor aber schon. Deshalb wäre eine solche Implementierung doch langsamer.<br />
Gibt es denn sonst noch Vorteile, die für eine Implementierung in deinem Sinne sprechen?</p>
<p>---</p>
<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Wenn du size als unisgned definierst, dann sparst du dir diese Ueberpruefung (und du hast dann auch kein memory leak mehr).</p>
</blockquote>
<p>Kurz: Vorgaben <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";-)"
      alt="😉"
    /></p>
<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Viel besser ist es den operator- mit Hilfe des operator-= zu implementieren.</p>
</blockquote>
<p>Jo, stimmt. Das könnte man machen.</p>
<p>---</p>
<p>Nexus schrieb:</p>
<blockquote>
<p>Wieso wirfst du die Exception eigentlich auf dem Heap? Also</p>
<pre><code class="language-cpp">throw new invalid_argument(&quot;Argument must be greater than zero!&quot;);
</code></pre>
</blockquote>
<p>Wie sollte ich es denn machen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643439</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643439</guid><dc:creator><![CDATA[Hador_]]></dc:creator><pubDate>Sun, 11 Jan 2009 16:10:13 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 16:11:21 GMT]]></title><description><![CDATA[<p>Hador_ schrieb:</p>
<blockquote>
<p>volkard schrieb:</p>
<blockquote>
<p>wohl besser, du implementiertst den copy-ctor normal und dern op= mit copy&amp;swap?</p>
</blockquote>
<p>Aber im op= muss doch nicht immer jedes Element neu erzeugt werden, im cp-ctor aber schon. Deshalb wäre eine solche Implementierung doch langsamer.<br />
Gibt es denn sonst noch Vorteile, die für eine Implementierung in deinem Sinne sprechen?</p>
</blockquote>
<p>oh, du verwendest ja die alten knoten weiter.<br />
ich nehme meinen vorschlag zurück. aber irgendwie fühle ich mich unwohl dabei. weiß auch nicht, warum.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643444</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643444</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 16:11:21 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 16:13:20 GMT]]></title><description><![CDATA[<p>Hador_ schrieb:</p>
<blockquote>
<p>Wie sollte ich es denn machen?</p>
</blockquote>
<p>Zum Beispiel so: <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<pre><code class="language-cpp">throw invalid_argument(&quot;Argument must be greater than zero!&quot;);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1643445</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643445</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 11 Jan 2009 16:13:20 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 17:41:10 GMT]]></title><description><![CDATA[<p>So, ich habe nun (fast) alle Anregungen mal umgesetzt. Damit sieht das ganze nun so aus:</p>
<pre><code class="language-cpp">#ifndef SPARSEVEKTOR_HPP_INCLUDED
#define SPARSEVEKTOR_HPP_INCLUDED

#include &lt;stdexcept&gt;

// A linked-list node for the sparse vector elements
template &lt;class T&gt; class Node {
	public:
		// Node constructor - simply initializes the data-members.
		Node(int idx, T val, Node *nxt)
		: index(idx), value(val), next(nxt) {}

		Node()
		: index(-1), next(NULL) {}

		inline int getIndex() const {
			return index;
		}

		inline void setIndex(const int idx) {
			index = idx;
		}

		inline Node * getNext() const {
			return next;
		}

		inline void setNext(Node&lt;T&gt; * nextNode) {
			next = nextNode;
		}

		inline T getValue() const {
			return value;
		}

		inline void setValue(const T val) {
			value = val;
		}

		bool operator == (const Node&lt;T&gt; &amp; n) const {
			return (index == n.index) &amp;&amp; (value == n.value);
		}

		bool operator != (const Node&lt;T&gt; &amp; n) const {
			return !(*this == n);
		}

	private:
		int index; // Element number, in the range [0, size)
		T value; // The value of this element.
		Node *next; // A pointer to the next node in the linked-list.
};

template &lt;class T&gt; class SparseVector {
	public:
		SparseVector(const int size = 1)
		: size(size), elements(new Node&lt;T&gt;()) {
			if (size &lt;= 0)
				throw std::invalid_argument(&quot;Argument must be greater than zero!&quot;);
		}

		SparseVector(const SparseVector&lt;T&gt; &amp; spvc)
		: size(spvc.size), elements(new Node&lt;T&gt;()) {
			*this = spvc;
		}

		~SparseVector() {
			Node&lt;T&gt; * aktElem = elements;
			while (aktElem) {
				Node&lt;T&gt; * nextElem = aktElem-&gt;getNext();
				delete aktElem;
				aktElem = nextElem;
			}
		}

		void print(std::ostream &amp; out, const std::string seperator) {
			for (int i = 0; i &lt; size; i++) {
				out &lt;&lt; getElement(i) &lt;&lt; seperator;
			}
		}

		T getElement(const int col) const {
			if ((col &lt; 0) || (col &gt;= size))
				throw std::out_of_range(&quot;Not a valid vector element!&quot;);
			Node&lt;T&gt; * elem = elements;
			while ((elem) &amp;&amp; (elem-&gt;getIndex() &lt; col))
				elem = elem-&gt;getNext();
			if (elem &amp;&amp; (elem-&gt;getIndex() == col))
				return elem-&gt;getValue();
			return 0;
		}

		void setElement(const int col, const T value) {
			if ((col &lt; 0) || (col &gt;= size))
				throw std::out_of_range(&quot;Not a valid vector element!&quot;);
			Node&lt;T&gt; * lastElem = elements;
			Node&lt;T&gt; * aktElem = elements-&gt;getNext();
			while ((aktElem) &amp;&amp; (aktElem-&gt;getIndex() &lt; col)) {
				lastElem = aktElem;
				aktElem = aktElem-&gt;getNext();
			}
			if (!aktElem || (aktElem-&gt;getIndex() != col)) {
				if (value != 0)
					lastElem-&gt;setNext(new Node&lt;T&gt;(col, value, aktElem));
			} else if (value == 0) {
				lastElem-&gt;setNext(aktElem-&gt;getNext());
				delete aktElem;
			} else {
				aktElem-&gt;setValue(value);
			}
		}

		inline int getSize() {
			return size;
		}

		SparseVector &amp; operator = (const SparseVector &amp; spvc) {
			if (this == &amp;spvc)
				return *this;
			size = spvc.size;

			Node&lt;T&gt; * aktElem = elements;
			Node&lt;T&gt; * newElem = spvc.elements-&gt;getNext();

			// overwrite existing nodes
			while (aktElem-&gt;getNext() &amp;&amp; newElem) {
				aktElem = aktElem-&gt;getNext();
				aktElem-&gt;setIndex(newElem-&gt;getIndex());
				aktElem-&gt;setValue(newElem-&gt;getValue());
				newElem = newElem-&gt;getNext();
			}
			if (newElem) { // add new nodes
				while (newElem) {
					aktElem-&gt;setNext(new Node&lt;T&gt;(*newElem));
					newElem = newElem-&gt;getNext();
					aktElem = aktElem-&gt;getNext();
				}
			} else { // delete existing nodes
				aktElem = aktElem-&gt;getNext();
				while (aktElem) {
					Node&lt;T&gt; * nextElem = aktElem-&gt;getNext();
					delete aktElem;
					aktElem = nextElem;
				}
			}
			return *this;
		}

		bool operator == (const SparseVector &amp; spvc) const {
			if (spvc.size != size)
				return false;
			Node&lt;T&gt; * aElem = elements-&gt;getNext();
			Node&lt;T&gt; * bElem = spvc.elements-&gt;getNext();
			while (aElem &amp;&amp; bElem &amp;&amp; (*aElem == *bElem)) {
				aElem = aElem-&gt;getNext();
				bElem = bElem-&gt;getNext();
			}
			return !aElem &amp;&amp; !bElem;
		}

		bool operator != (const SparseVector &amp; spvc) const {
			return !(*this == spvc);
		}

		SparseVector operator + (const SparseVector &amp; spvc) const {
			checkDimensionError(spvc);
			SparseVector result(*this);
			return result += spvc;
		}

		SparseVector operator - (const SparseVector &amp; spvc) const {
			checkDimensionError(spvc);
			SparseVector result(*this);
			return result -= spvc;
		}

		SparseVector &amp; operator += (const SparseVector &amp; spvc) {
			checkDimensionError(spvc);
			for (int i = 0; i &lt; size; i++) {
				setElement(i, getElement(i) + spvc.getElement(i));
			}
			return *this;
		}

		SparseVector &amp; operator -= (const SparseVector &amp; spvc) {
			checkDimensionError(spvc);
			for (int i = 0; i &lt; size; i++) {
				setElement(i, getElement(i) - spvc.getElement(i));
			}
			return *this;
		}
	private:
		int size;
		Node&lt;T&gt; * elements;

		inline void checkDimensionError(const SparseVector &amp; spvc) const {
			if (size != spvc.size)
				throw std::invalid_argument(&quot;Dimension must be the same!&quot;);
		}
};

#endif // SPARSEVEKTOR_HPP_INCLUDED
</code></pre>
<p>Danke auf jeden Fall schonmal für die vielen Kommentare - wer weitere hat: immer her damit ^^</p>
<p>Gruß Lars</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643489</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643489</guid><dc:creator><![CDATA[Hador_]]></dc:creator><pubDate>Sun, 11 Jan 2009 17:41:10 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 18:44:20 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">#ifndef SPARSEVEKTOR_HPP_INCLUDED
#define SPARSEVEKTOR_HPP_INCLUDED

#include &lt;stdexcept&gt;

// A linked-list node for the sparse vector elements
template &lt;class T&gt; class Node {
	public:
		// Node constructor - simply initializes the data-members.
		Node(int idx, T val, Node *nxt)
		: index(idx), value(val), next(nxt) {}
//T const&amp; val, damits schneller geht bei z.B. sttrings
//size_t idx, oder? sind negative indizes möglich?

		Node()
		: index(-1), next(NULL) {}
//wozu? ist zeitverschwendung und bringt nichmal sicherheit. 

		inline int getIndex() const {
			return index;
		}
//die zugriffsfunktionen alle weg, dafür die attribute public machen. 
//die main() kommt eh NIE ein Node-Objet in die hand. was soll passieren?

		inline void setIndex(const int idx) {
			index = idx;
		}

		inline Node * getNext() const {
			return next;
		}

		inline void setNext(Node&lt;T&gt; * nextNode) {
			next = nextNode;
		}

		inline T getValue() const {
			return value;
		}
//T const&amp;, aber egal, fliegt ja weg

		inline void setValue(const T val) {
			value = val;
		}

		bool operator == (const Node&lt;T&gt; &amp; n) const {
			return (index == n.index) &amp;&amp; (value == n.value);
		}
//wozu?

		bool operator != (const Node&lt;T&gt; &amp; n) const {
			return !(*this == n);
		}

	private:
		int index; // Element number, in the range [0, size)
		T value; // The value of this element.
		Node *next; // A pointer to the next node in the linked-list.
//umsortieren zu index,next,value oder next,index,value. je nachdem, was 
//schneller sein soll, index oder next. value ans ende, weil größe unbekannt, 
//um kein überraschendes padding hervorzuholen
};

template &lt;class T&gt; class SparseVector {
	public:
		SparseVector(const int size = 1)
		: size(size), elements(new Node&lt;T&gt;()) {
			if (size &lt;= 0)
				throw std::invalid_argument(&quot;Argument must be greater than zero!&quot;);
		}
//warum nicht size=0?

		SparseVector(const SparseVector&lt;T&gt; &amp; spvc)
		: size(spvc.size), elements(new Node&lt;T&gt;()) {
			*this = spvc;
		}
//warum zuerst size und elements setzen und dann doch op= aufrufen?

		~SparseVector() {
			Node&lt;T&gt; * aktElem = elements;
			while (aktElem) {
				Node&lt;T&gt; * nextElem = aktElem-&gt;getNext();
				delete aktElem;
				aktElem = nextElem;
			}
		}

		void print(std::ostream &amp; out, const std::string seperator) {
			for (int i = 0; i &lt; size; i++) {
				out &lt;&lt; getElement(i) &lt;&lt; seperator;
			}
		}

		T getElement(const int col) const {
//T const&amp; getEle...
			if ((col &lt; 0) || (col &gt;= size))
				throw std::out_of_range(&quot;Not a valid vector element!&quot;);
//&lt;0 fällt weg wegen size_t
			Node&lt;T&gt; * elem = elements;
			while ((elem) &amp;&amp; (elem-&gt;getIndex() &lt; col))
				elem = elem-&gt;getNext();
			if (elem &amp;&amp; (elem-&gt;getIndex() == col))
				return elem-&gt;getValue();
			return 0;
		}
//gefällt mir gar nicht. wenn du 0 geben willst bei nichtfund, dann nimme nen 
//zeiger als rückgabe. 
//war nicht eher (suchschleifenidiom: gehe über alle elemente - if hatwas - return -  sag hatnix)
for(Node&lt;T&gt; * elem = elements;elem!=0;elem=elem-&gt;next)
   if(elem-&gt;index==col)
      return &amp;elem-&gt;value;
return 0;
//gemeint?
//andererseite, wer bei indexgrenzenfehlern ne exceptions wirft, darf hier auch 
//eine werfen. ich würde bei beiden arten von fehler keine werfen. 
		void setElement(const int col, const T value) {
//const T&amp; value
			if ((col &lt; 0) || (col &gt;= size))
				throw std::out_of_range(&quot;Not a valid vector element!&quot;);
			Node&lt;T&gt; * lastElem = elements;
			Node&lt;T&gt; * aktElem = elements-&gt;getNext();
			while ((aktElem) &amp;&amp; (aktElem-&gt;getIndex() &lt; col)) {
				lastElem = aktElem;
				aktElem = aktElem-&gt;getNext();
			}
			if (!aktElem || (aktElem-&gt;getIndex() != col)) {
				if (value != 0)
					lastElem-&gt;setNext(new Node&lt;T&gt;(col, value, aktElem));
			} else if (value == 0) {
//bedenklich. oder willste nen zeiger als value nehmen? wäre auch nicht hübsch. 
//oder ist die klasse in wirklichkeit ein SparseNumericVector, der nur 
//zahlentypen tragen soll?
				lastElem-&gt;setNext(aktElem-&gt;getNext());
				delete aktElem;
			} else {
				aktElem-&gt;setValue(value);
			}
		}
//scheint gut

		inline int getSize() {
//size_t getSize() const
//man schreibt inline nicht mehr
			return size;
//wurde size überhaupt beim insert upgedated? nee, gell?
//und warum nicht? weil size eh nix bringt, füchte ich. 
		}

		SparseVector &amp; operator = (const SparseVector &amp; spvc) {
			if (this == &amp;spvc)
				return *this;
			size = spvc.size;

			Node&lt;T&gt; * aktElem = elements;
			Node&lt;T&gt; * newElem = spvc.elements-&gt;getNext();

			// overwrite existing nodes
			while (aktElem-&gt;getNext() &amp;&amp; newElem) {
				aktElem = aktElem-&gt;getNext();
				aktElem-&gt;setIndex(newElem-&gt;getIndex());
				aktElem-&gt;setValue(newElem-&gt;getValue());
				newElem = newElem-&gt;getNext();
			}
			if (newElem) { // add new nodes
				while (newElem) {
					aktElem-&gt;setNext(new Node&lt;T&gt;(*newElem));
					newElem = newElem-&gt;getNext();
					aktElem = aktElem-&gt;getNext();
				}
			} else { // delete existing nodes
				aktElem = aktElem-&gt;getNext();
				while (aktElem) {
					Node&lt;T&gt; * nextElem = aktElem-&gt;getNext();
					delete aktElem;
					aktElem = nextElem;
				}
			}
			return *this;
		}

		bool operator == (const SparseVector &amp; spvc) const {
//global machen, oder?
			if (spvc.size != size)
				return false;
			Node&lt;T&gt; * aElem = elements-&gt;getNext();
			Node&lt;T&gt; * bElem = spvc.elements-&gt;getNext();
			while (aElem &amp;&amp; bElem &amp;&amp; (*aElem == *bElem)) {
				aElem = aElem-&gt;getNext();
				bElem = bElem-&gt;getNext();
			}
			return !aElem &amp;&amp; !bElem;
//also return aElem || bElem//ka, was hübscher ist
//ich hätte vermutlich eher geschrieben
//for(;aElem!=0 or bElem!=0;aElem=aElem-&gt;next,bElem=bElem-&gt;next)
//   if(aElem-&gt;index!=bElem-&gt;index)
//     if(!(aElem-&gt;value==bElem-&gt;value))//bzw != bei SparseNumericVector
//        return false
//return true;
		}

		bool operator != (const SparseVector &amp; spvc) const {
//auch global?
			return !(*this == spvc);
		}

		SparseVector operator + (const SparseVector &amp; spvc) const {
//auch global. 
			checkDimensionError(spvc);
			SparseVector result(*this);
//nachlesen, ob du hier die RVO kaputtmachst. evtl die beiden zeilen 
//vertauschen. war da nicht sowas?
			return result += spvc;
		}

		SparseVector operator - (const SparseVector &amp; spvc) const {
			checkDimensionError(spvc);
			SparseVector result(*this);
			return result -= spvc;
		}

		SparseVector &amp; operator += (const SparseVector &amp; spvc) {
			checkDimensionError(spvc);
			for (int i = 0; i &lt; size; i++) {
//nee, ganz gewiss ne schleife über die Nodes, nicht über die 
//sparsen indizes. 
//und hier liegt der hund begraben!!!
//deswegen also die nutzlose size. aha!
//ja, das mach mal runter von O(anzahlKnoten*maxIndex) zu O(anzahlKnoten)
				setElement(i, getElement(i) + spvc.getElement(i));
			}
			return *this;
		}

		SparseVector &amp; operator -= (const SparseVector &amp; spvc) {
			checkDimensionError(spvc);
			for (int i = 0; i &lt; size; i++) {
//auch hund
				setElement(i, getElement(i) - spvc.getElement(i));
			}
			return *this;
		}
	private:
		int size;
		Node&lt;T&gt; * elements;

		inline void checkDimensionError(const SparseVector &amp; spvc) const {
			if (size != spvc.size)
				throw std::invalid_argument(&quot;Dimension must be the same!&quot;);
		}
};

#endif // SPARSEVEKTOR_HPP_INCLUDED
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1643523</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643523</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 18:44:20 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 19:19:27 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<pre><code class="language-cpp">//umsortieren zu index,next,value oder next,index,value. je nachdem, was 
//schneller sein soll, index oder next. value ans ende, weil größe unbekannt, 
//um kein überraschendes padding hervorzuholen
</code></pre>
</blockquote>
<p>Kannst du das ein bißchen näher erläutern? Warum sollte das Padding (mit Standard-Compiler-Optionen) zum Problem werden? Und vor allem, welchen Unterschied macht die Reihenfolge von index und next?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643539</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643539</guid><dc:creator><![CDATA[dooooomi]]></dc:creator><pubDate>Sun, 11 Jan 2009 19:19:27 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 19:32:49 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">//nur mal in notepad hingehudelt:
//annahme: die nodes liegen nach index sortiert im vector vor

elem* appendOne(elem* dst,size_t index,T const&amp; value)
{
   dst-&gt;next=new Node(0,index,value);
   return dst-&gt;next;
}

elem* appendCopy(elem* dst,elem* src)
{
   while(src!=0)
      dst=appendOne(dst,src-&gt;index,src-&gt;value);
}

elem* add(elem* pa,elem* pb)
{
   while(pa!=0 and pb!=0)
   {
      if(pa-&gt;index==pb-&gt;index)
      {
         pc=appendOne(pc,pa-&gt;value+pb-&gt;value);
         pa=pa-&gt;next;
         pb=pb-&gt;next;
      }
      else if(pa-&gt;index&lt;pb-&gt;index)
      {
         pc=appendOne(pc,pa-&gt;value);
         pa=pa-&gt;next;
      }
      else
      {
         pc=appendOne(pc,pb-&gt;value);
         pb=pb-&gt;next;
      }
   }
   if(pa!=0)
      pc=appendCopy(pc,pa)
   if(pb!=0)
      pc=appendCopy(pc,pb)

}

vector operator+(vector a,vector b)
{
   return vector(add(a-&gt;start,b-&gt;start));
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1643550</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643550</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 19:32:49 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 19:40:28 GMT]]></title><description><![CDATA[<p>dooooomi schrieb:</p>
<blockquote>
<p>volkard schrieb:</p>
<blockquote>
<pre><code class="language-cpp">//umsortieren zu index,next,value oder next,index,value. je nachdem, was 
//schneller sein soll, index oder next. value ans ende, weil größe unbekannt, 
//um kein überraschendes padding hervorzuholen
</code></pre>
</blockquote>
<p>Kannst du das ein bißchen näher erläutern? Warum sollte das Padding (mit Standard-Compiler-Optionen) zum Problem werden? Und vor allem, welchen Unterschied macht die Reihenfolge von index und next?</p>
</blockquote>
<p>das erste member hat potentiell den schnellsten zugriff, denn da muß keine arithmetik mehr geschehen zwischen dem objektzeiger und dem zeiger aufs member.<br />
also sucht man sich aus, ob index oder next den ehrenplatz bekommen soll. falls man jetzt schon abschätzen kann, welches attribut deutlich häufiger verwendet wird. kann man's nicht, isses vermutlich auch nicht deutlich messbar. dann läßt man es oder verschiebt die reihenfolgenfestlegung bis man einen praxisnahen datensatz hat und mißt kurz.<br />
padding wird überraschend bei int(32)index, double(64)daten, T*(32)next, wenn der compiler die daten 64-aligned halten will, dann steht da int(32)index, dummy(32), double(64)daten, T*(32)next, dummy(32). und weil vermutlich sizeof(T*)==sizeof(size_t) ist man's vermutlich immer los, wenn die daten am ende stehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643554</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643554</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 19:40:28 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 21:02:18 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>das erste member hat potentiell den schnellsten zugriff, denn da muß keine arithmetik mehr geschehen zwischen dem objektzeiger und dem zeiger aufs member.<br />
also sucht man sich aus, ob index oder next den ehrenplatz bekommen soll. falls man jetzt schon abschätzen kann, welches attribut deutlich häufiger verwendet wird. kann man's nicht, isses vermutlich auch nicht deutlich messbar. dann läßt man es oder verschiebt die reihenfolgenfestlegung bis man einen praxisnahen datensatz hat und mißt kurz.</p>
</blockquote>
<p>Macht das wirklich einen Geschwindigkeits-Unterschied, der in der Praxis relevant ist? Ich bezweifle nicht, daß der Zugriff auf das erste Member schneller sein kann, aber trotzdem wäre das so ziemlich das letzte, worüber ich mir beim Schreiben des Codes Gedanken machen würde (das böse P-Wort spare ich mir jetzt mal ;)).</p>
<p>volkard schrieb:</p>
<blockquote>
<p>padding wird überraschend bei int(32)index, double(64)daten, T*(32)next, wenn der compiler die daten 64-aligned halten will, dann steht da int(32)index, dummy(32), double(64)daten, T*(32)next, dummy(32). und weil vermutlich sizeof(T*)==sizeof(size_t) ist man's vermutlich immer los, wenn die daten am ende stehen.</p>
</blockquote>
<p>Nur daß ich das richtig verstehe: es geht dir um den Speicherbedarf des Objekts, nicht um die Geschwindigkeit der Zugriffe?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643585</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643585</guid><dc:creator><![CDATA[dooooomi]]></dc:creator><pubDate>Sun, 11 Jan 2009 21:02:18 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Sun, 11 Jan 2009 21:26:00 GMT]]></title><description><![CDATA[<p>dooooomi schrieb:</p>
<blockquote>
<p>Macht das wirklich einen Geschwindigkeits-Unterschied, der in der Praxis relevant ist?</p>
</blockquote>
<p>nicht relevant, unter besten umständen vielleicht ein prozent. aber hier kostenlos und unbedenklich. später denke ich nicht mehr dran, da mach ichs gleich.</p>
<p>dooooomi schrieb:</p>
<blockquote>
<p>volkard schrieb:</p>
<blockquote>
<p>padding wird überraschend bei int(32)index, double(64)daten, T*(32)next, wenn der compiler die daten 64-aligned halten will, dann steht da int(32)index, dummy(32), double(64)daten, T*(32)next, dummy(32). und weil vermutlich sizeof(T*)==sizeof(size_t) ist man's vermutlich immer los, wenn die daten am ende stehen.</p>
</blockquote>
<p>Nur daß ich das richtig verstehe: es geht dir um den Speicherbedarf des Objekts, nicht um die Geschwindigkeit der Zugriffe?</p>
</blockquote>
<p>ja.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643598</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643598</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 11 Jan 2009 21:26:00 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Mon, 12 Jan 2009 00:01:22 GMT]]></title><description><![CDATA[<p>Hallo volkard,<br />
... das ist mal ausführlich ^^</p>
<p>Zunächst muss ich allerdings mal ein Missverständnis korregieren: Das ganze soll einen Vektor im mathematischen sinne darstellen. Size ist somit die Dimension des Vektors. Das ganze sollte so umgesezt werden, dass Elemente, die 0 sind nicht gespeichert werden (aber es gibt eben dennoch alle Elemente im Bereich 0 &lt;= x &lt; size). Dementsprechend macht meine Implementierund dann hoffentlich auch wieder an vielen Stellen Sinn.</p>
<p>Von deinen Tips habe ich noch einige umgesetzt:</p>
<ul>
<li>Node habe ich nun als Memberklasse von SparseVector implementier (da muss ja eh kein anderer dran) und die ganzen Getter/Setter entfernt (Klasse private aber alle Attribute public)</li>
<li>copy-ctor: Anfangsinitialisierung von size entfernt.</li>
<li>getSize konstant deklariert</li>
</ul>
<p>Weiter schreibst du aber noch, dass du die ganzen Operatoren global deklarieren würdest. Warum?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643674</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643674</guid><dc:creator><![CDATA[Hador_]]></dc:creator><pubDate>Mon, 12 Jan 2009 00:01:22 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Mon, 12 Jan 2009 00:28:43 GMT]]></title><description><![CDATA[<p>Hador_ schrieb:</p>
<blockquote>
<p>Weiter schreibst du aber noch, dass du die ganzen Operatoren global deklarieren würdest. Warum?</p>
</blockquote>
<p>wenn du mal nen ctor baust, der zum beispiel einen vector&lt;int&gt; nimmt.<br />
dann kannste ja machen<br />
vector&lt;int&gt; a=holeVectorVonFremdanbieter();<br />
SparseVector&lt;int&gt; b;<br />
//...b initialisieren<br />
SparseVector&lt;int&gt; c=b+a;<br />
aber nicht<br />
SparseVector&lt;int&gt; c=a+b;<br />
das verwirrt.<br />
also globaler op+ sind linker und rechter operand gleicher.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643678</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643678</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 12 Jan 2009 00:28:43 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Mon, 12 Jan 2009 00:59:24 GMT]]></title><description><![CDATA[<p>Hador_ schrieb:</p>
<blockquote>
<p>Size ist somit die Dimension des Vektors.</p>
</blockquote>
<p>ok.</p>
<blockquote>
<p>Das ganze sollte so umgesezt werden, dass Elemente, die 0 sind nicht gespeichert werden (aber es gibt eben dennoch alle Elemente im Bereich 0 &lt;= x &lt; size). Dementsprechend macht meine Implementierund dann hoffentlich auch wieder an vielen Stellen Sinn.</p>
</blockquote>
<p>ja, aber meinen vorschlag beim operator+ mag ich nochmal darlegen.<br />
erstmal vorweg: wenn der vector immer sortiert vorliegen würde, wären die suchläufe im durchschnitt nur halb so lang bei treffern und genausolang bei nichttreffern. es kostet also wohl nix dazu, die liste als sortierte liste zu machen. und es ist auch ohne großen aufwand machbar.<br />
nun nehme ich mal an, ich hab zwei dünn besetzte vektoren jeweils mit dimension 1000 und jeweils nur 50 komponeneten, die ungleich 0 sind.<br />
das sollte doch dein hauptanwendungsgebiet sein, hoffe ich.<br />
dein operator+ läuft in der äüßeren schleife von 0 bis 999 und sucht für beide vektoren von anfang bis ende, was zusammen 100 angeschaute elemente ergibt. also 1000-mal müssen alle elemente angeschaut werden.<br />
mein gegenvorschlag braucht nur einmal alle elemente anzuschauen. der geht ungefähr wie der merge-schritt im merge-sort.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643680</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643680</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 12 Jan 2009 00:59:24 GMT</pubDate></item><item><title><![CDATA[Reply to Codequalität on Mon, 12 Jan 2009 01:03:13 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>erstmal vorweg: wenn der vector immer sortiert vorliegen würde, wären die suchläufe im durchschnitt nur halb so lang bei treffern und genausolang bei nichttreffern. es kostet also wohl nix dazu, die liste als sortierte liste zu machen. und es ist auch ohne großen aufwand machbar.</p>
</blockquote>
<p>Die Liste ist doch sortiert <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";-)"
      alt="😉"
    /></p>
<p>volkard schrieb:</p>
<blockquote>
<p>dein operator+ läuft in der äüßeren schleife von 0 bis 999 und sucht für beide vektoren von anfang bis ende, was zusammen 100 angeschaute elemente ergibt. also 1000-mal müssen alle elemente angeschaut werden.<br />
mein gegenvorschlag braucht nur einmal alle elemente anzuschauen.</p>
</blockquote>
<p>Da hast du recht. das könnte man noch beschleunigen, indem man die Listen beider Vektoren durchgeht, bei gleichem Index addiert und ansonsten das jeweilige Element direkt einfügt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1643683</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1643683</guid><dc:creator><![CDATA[Hador_]]></dc:creator><pubDate>Mon, 12 Jan 2009 01:03:13 GMT</pubDate></item></channel></rss>