When to return a reference and when to return a copy?

dotminic
  • When to return a reference and when to return a copy? dotminic

    I was looking at the d3dx math .h and noticed that a difference between the "+" and "+=" operators:

    D3DXVECTOR3& operator += ( CONST D3DXVECTOR3& );
    D3DXVECTOR3 operator + ( CONST D3DXVECTOR3& ) const;
    

    Why is it returning a reference in the case of a += operation and a copy in the case of + operation ?

    I'm guessing in the first case it's modifying the vector on which you call the += operation, something like this:

    this->_x += x;
    ...
    return *this;
    

    and in the case of a + operation it would be doing something like this:

    return D3DXVECTOR3(this->_x + x, this->_y + y, this->_z + z);
    

    That being said, if that's what happens in the D3DXVECTOR3 implementation, why not return a reference in the case of + operation ?

  • In the operator += case, the method is probably modifying the calling object in place. On the other hand, operator + is creating a new D3DXVECTOR3 that is the sum of the calling object and the argument.

  • You return a reference to the original vector in a += because you are modifying the actual vector itself and the vector will not fall out of scope.

    While in a + you do not want any modification of the original vector. Instead a + operator computes a new value and uses copy constructors to return the value.

    If you would try something like

    D3DXVECTOR3 newVal = D3DXVECTOR3(this->_x + x, this->_y + y, this->_z + z);
    return &newVal;
    

    You would return a reference to a vector which fell out of scope and therefore will be cleaned up very soon.

  • Why is a reference returned for += ?

    A reference is returned because the object is (likely) being modified directly, and as such it wouldn't make sense to create a copy for the sole purpose of returning one.

    Note that the reference can still be converted to a copy by other operations (such as =):

    D3DXVECTOR3 a (1,2,3);
    D3DXVECTOR3 b (1,2,3);
    a+=b;                 //no copy made
    D3DXVECTOR3 c = a+=b; //one copy made
    

    So this approach (returning by reference) allows for the least amount of work to be done in each situation.

    Why is a reference NOT returned for + ?

    A reference is not returned for + because a copy is made as part of the operation, so it's returned. Consider what would happen if you added two D3DXVECTOR3's together, like this: (a + b). Which of the two objects should the result be referencing? Well obviously the answer is neither - the result should be a copy. Hence a copy is returned.

Tags
c++ directx vector
Related questions and answers
  • () { } Cube::~Cube() { pBuffer->Release(); // why does this only work when put here? because it's created here? I thnk so, why not iBuffer though? } void Cube::Draw() { render_frame(); } void Cube... pBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &pVoid); // map the vertex buffer memcpy(pVoid, OurVertices, sizeof(OurVertices)); // copy the vertices to the buffer pBuffer->Unmap...* pVoid; // redefinition iBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &pVoid); // map the index buffer memcpy(pVoid, OurIndices, sizeof(OurIndices)); // copy the indices to the buffer

  • Like many beginner graphics programmers I followed a tutorial which showed me how to set up buffer descriptions and fill out the vertex buffer etc... - the steps involved in drawing a simple indexed cube on the screen. There is a leap however when it comes to drawing more than one of these cubes. My code below is the original cube drawing code, if called more than once, each call overwrites...; bd.MiscFlags = 0; device->CreateBuffer(&bd, NULL, &pBuffer); void* pVoid; // the void pointer pBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &pVoid); // map the vertex buffer

  • ; case OLD: return old_map[Y]; break;}}; char get_contents (int X, int Y, int comm= NEW){switch(comm){ case NEW: return new_map[Y][X]; break; case OLD: return old_map[Y][X]; break;}}; //////////////////////////////////////////// Refresh...((char*)new_map[r].c_str());} // make sure this works later // Insert Time if(command== ALL || command== TIME){ enum{ time_loc_y= 22, time_loc_x= 38

  • // of Resource. Note it only hands give a const reference to the Resource, as // it is read only. template <class T> class ResourceGuard { public: ResourceGuard(T *_resource): resource(_resource) { resource-&gt;reference(); } virtual ~ResourceGuard() { resource-&gt;dereference();} const T* operator*() const { return (resource); } }; class ResourceManager...) { // Calls a private method, pretend it exits T *temp = dynamic_cast<T*&gt; (_getResource(resourceId)); assert(temp != NULL); return (ResourceGuard<T>(temp

  • i think i just found the solution. 1) the problem is that backbuffer surface and source surface are of different formats - that is why exception was thrown. 2) the image path needed double slash "C...(D3D_SDK_VERSION))) return false; std::wstring wsPath = L"C:\wood.bmp"; // path to the image D3DXIMAGE_INFO Info; if (FAILED(D3DXGetImageInfoFromFile(wsPath.c_str(), &amp;Info...); //================================================================================================================================// code starts here //================// int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if (!initWindow(hInstance)) return

  • the source and buffer objects into C++ classes. I got as far as the source class. My function which returns the number of processed buffers is not altering the integer passed to alGetSourcei. int ALSource::GetBuffersProcessed() const { ALint processed; alGetSourcei(this-&gt;source, AL_BUFFERS_PROCESSED, &amp;processed); int error = alGetError(); if(error != AL_NO_ERROR) return -1; return processed; } I checked that error is never anything but AL_NO_ERROR. I generate the source in the constructor: alGenSources(1, &amp;source); This also never gives any error

  • = data[1][i]; short val_right = (short)(coeff_right * 0x7FFF); // handle endianness if ( !littleEndian ) { val_left = ((val_left &amp; 0xff) << 8) | (val_left &gt;&gt; 8); val_right = ((val_right &amp; 0xff) << 8) | (val_right &gt;&gt; 8); } conversion[i*2+0] = val_left; conversion[i*2+1] = val_right; } fwrite((void*)&amp;conversion[0... outputting four beats in time. When I playback the wave-file, the beats timing is correct but it just sounds way fuzzy and clipped. Am I doing something wrong with my calculation? I am exporting

  • ); When using this code I'm able to detect a ray intersection via a sphere, but I have questions when determining an intersection via a plane. First off should I be using my vRayOrig &amp; vRayDir variables for the plane intersection tests or should I be using the new vectors that are created for use in object space? When looking at a site like this for example: http://www.tar.hu... are giving me trouble. I've tried to understand various sources and get hung up on some of the variables used within their explanations. Here is a snippet of my code: bool Picking() { D3DXVECTOR3

  • it returned: %i", rval); return 1; } allegro_message("Setting Graphics Mode...Press X To Begin Game. Default Missile count: %i", bullets-&gt;size()); set_color_depth(32); int ret... but when I press the X button on the PSP I see no bullet being drawn or updated on the screen. I know the problem doesn't lie with the pad because I press start and it exits my game so I do not think... Missile { private: static const double angle = (3.14159265358979323846 / 2); public: bool Alive; static const int V = 5; double X; double Y

Data information