C++ are std::wstrings passed by reference or is a copy made?

Are std::wstrings passed by reference or is a copy made?
MyFunc(std::wstring s)
{
}

Open in new window

Am I receiving a copy of the string, or a pointer to the original string.
deleydAsked:
Who is Participating?
 
sarabandeCommented:
A& is passing A by reference.

A& is a c++ reference type referencing to an object of class A by 'address'. different to a pointer it is not a second variable but a reference (alias) to a the original A object, for example when passed as argument by the caller.

A&& is the new (pre-C++11 and C++11)  'move' value_type which describes a so-called 'xvalue' (opposed to value types 'lvalue' and 'rvalue', which describe at which side -left or right - of an assignment the variable can be used).

Only the following expressions are xvalues:
- A function call expression, if the function's return type is an rvalue reference
  to object type, such as std::move(val)
- A cast expression to an rvalue reference to object type, such as static_cast<T&&>(val)
  or (T&&)val
- a non-static class member access expression, in which the object expression
  is an xvalue
- A pointer-to-member expression in which the first operand is an xvalue and
  the second operand is a pointer to data member.


the xvalue is a value category used for moving objects in containers. if for example elements were sorted in a std::vector you of course would not create (deep) copies of each pair of elements that were swapped. so a 'move' object normally is a 'flat' copy of the original object (beside the 'move' constructor would make a difference) for temporary use. it is writeable but different to a pure reference it would not change the original object as it has a new address and is a separate object.

as ambience has shown the T&& type allows to define new overrides of constructors and functions which could implement a special handling for those xvalues.

see http://en.cppreference.com/w/cpp/language/value_category for details

Sara
0
 
jkrCommented:
In your example, you are indeed passing a copy of the string by value. When calling 'MyFunc()', the compiler generates code that copies the contents of 's' to the calling function's stack into a new 'wstring' instance. If you want to pass a reference, use '&', e.g.

MyFunc(std::wstring& s) // pass a reference instead
{
}
                                  

Open in new window


That does not only apply to 'wstring', but to all variables you could possibly pass.
0
 
chaauCommented:
With your implementation you will get a copy of the string. If you change the code to this:
MyFunc(std::wstring &s)
{
}

Open in new window

you'll get a reference. On a side note, MFC CString has a built-in smartness to automatically pass strings by reference when using the code similar to yours:
MyFunc(CString s) // no copy will be made, equivalent to "const CString &s"
{
}

Open in new window

0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
jkrCommented:
Just to make that clear: You are responsible to decide whether a variable is passed by reference or value. The compiler will make no asumptions about that.
0
 
sarabandeCommented:
to add to above comments:

std::wstring is typedef of template class std::basic_string<wchar_t>. basic_string internally uses reference counting for its internal string object (like most other string classes as well). that means if you make a copy of the wstring - like in your code - the new wstring object uses the same pointer as the original wstring and only the reference counter associated with the internal string object was incremented. the advantage of this technique is that copying strings don't add a penalty to the performance.

but, as these pointers were handled by the string class automatically, you don't have to care for.

MFC CString has a built-in smartness to automatically pass strings by reference when using the code similar to yours
CString also uses reference counting. but the CString object was a really copy which 'copied' the internal pointer member to the internal string object. so, it actually doesn't turn arguments from 'by value' to 'by reference', at least not in a technically manner.  

Sara
0
 
ambienceCommented:
It may be copied or moved - depends on the call-site. I've created a tiny example to explain the point. Replace A by wstring and the same semantics apply. In the case of wstring (since it is provided by STL) it is safe to assume that move semantics are available when you invoke std::move.


class A
{
public:
      A() {
            std::cout << "Default constructor" << std::endl;
      }
      A(const A& a) {
            std::cout << "Copy constructor" << std::endl;
      }
      A(A&& a) {
            std::cout << "Move constructor" << std::endl;
      }
};

class B
{
public:
         // Is 'a' copied in the traditional sense of copy? Maybe - Maybe not
      B(A a) {
      }
};

int main() {
      A a;
      B b1(a);                        
      B b2(std::move(a));  ---> Move Constructor/No Copy
}

-----------------
Output:
Default constructor
Copy constructor
Move constructor
0
 
sarabandeCommented:
It may be copied or moved - depends on the call-site

when adding an A& member to B and output the A address you see that the A passed via std::move has a new address, same as with copy constructor. in neither case, the original A object was passed by reference.

class A
{
public:
      A() {
            std::cout << "Default constructor " << this << std::endl;
      }
      A(const A& a) {
            std::cout << "Copy constructor " << this << std::endl;
      }
      A(A&& a) {
            std::cout << "Move constructor " << this << std::endl;
      }
};

class B
{
    A & mya;
public:
         // Is 'a' copied in the traditional sense of copy? Maybe - Maybe not
      B(A a) : mya(a) {
      }
};

int main() { 
      A a;
      std::cout << "main &a " << &a << std::endl;
      B b1(a);                        
      B b2(std::move(a));  // ---> Move Constructor/No Copy
      return 0;
}

output:
----------

Default constructor 0037FE4F
main &a 0037FE4F
Copy constructor 0037FD48
Move constructor 0037FD48

Open in new window



Sara
0
 
deleydAuthor Commented:
What is A& and A&& ?
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.