Copy C'tor&Ass. op

I had this exercise during my lecture, The answer are in the comments,
I had 2 which I did not understand, and the question is showed in the comment.

1
2
3
4
5
6
7
8
9
10
int main () {
String s0(“abc”); //C'tor-Why not copy C'tor? 
String s1 = s0;  //copy C'tor
String s2(s0); //copy C'tor
String s3=“abc”; //copy C'tor, why not just a C'tor? I was told during the lecture
                 //that this is a char* and a copy C'tor gets string only.
                 //So how come I see the diffrence between the string and a char*?
String s4; //
s4 = s3;
return 1; }
The copy ctor is called when one object gets copied to another object.

Example:
String s1 = s0;

This is the copy ctor because 's0' is a String object, and it is being copied to 's1'.

On the other hand...
String s0(“abc”);

This is NOT the copy ctor because "abc" is not a String object... and therefore this is not an object->object copy... but instead it is constructing an object from a string literal. So this is calling the ctor which takes a const char* as a parameter.

String s3=“abc”; //copy C'tor, why not just a C'tor?

This is NOT the copy ctor, for the same reason the above was not a copy ctor. The correct answer here is the 'normal' const char* ctor.
The normal order of calling constructors in the following line

String s3=“abc”;

is the following. At first the constructor with the first parameter of const char * is called. It creates a temporary object of type String. When the move (if defined) or copy constructor is called to create named object s3 from this temporary object. So in fact two constructors, one with a parameter and the second either the move constructor or the copy constructor, are called.

However the C++ Standard allows to eliminate the call of the move or copy constructor Nevertheless the copy or move constructor shall be acceptable.

Consider the code

1
2
3
4
5
6
7
8
9
struct String
{
   String( const char * ) { std::cout << "String::String( const char * )" << std::endl; }

private:
   String( const String & ) { std::cout << String::String( const String & )" << std::endl;
};

String s3 = "abc"; 

This code shall not be compiled (except that MS VC++ 2010 contains a bug and will compile this code:) ) because the copy constructor is inaccessible though it wouldl not be called if it were public.
Last edited on
How do I see the differences between a string a char*?
(How do I recognize each one of them?)

Vlad:
Why doesn't it call the Ass.op after converting the char* to a string?
Last edited on
I have not understood the question.
1
2
 
String s3=“abc”; 

Why "abc" is a char* and not a string?

As you said, in this code-line we are calling 2 constructors:
1)The first C'tor which convert this char* to a string(what is the name of this C'tor?)
2)a copy C'tor to copy this converted string to s3(why are we now calling op= ??)


Last thing,
I do not understand how to implement a copy C'tor, can anyone give me an example?

Thanks
EDIT: Vlad is correct ... my understanding was wrong. Disregard this post


I'm pretty sure vlad is mistaken.

String s3=“abc”;

This calls exactly one constructor: String(const char*);. It does not call or involve the copy constructor in any way.

The copy constructor is only involved when you do a String->String copy. Here, you are not doing that, but rather are doing const char*->String.
Last edited on
@Disch


I described all detailed. try the example I showed that is make the copy constructer private and the code will not be compiled. Or another example declare the copy constructor explicit and again the code will not be compiled.

1
2
3
4
5
6
7
8
9
struct String
{
   String( const char * ) { std::cout << "String::String( const char * )" << std::endl; }

private:
   String( const String & ) { std::cout << String::String( const String & )" << std::endl;
};

String s3 = "abc"; 


or

1
2
3
4
5
6
7
struct String
{
   String( const char * ) { std::cout << "String::String( const char * )" << std::endl; }
   explicit String( const String & ) { std::cout << String::String( const String & )" << std::endl;
};

String s3 = "abc"; 

The copy constructor must be accessible. The standard simply allows to eliminate the call of the copy constructor.
I can't try it now as the only compiler I have here is VS (which you already said it works on), but I would be very surprised if that were actually the case.

I had always been under the impression that String a = "foo"; and String a("foo"); were identical apart from the latter being explicit.

If you're right this draws into question this example:

1
2
3
4
5
6
7
8
void func( const String& a )
{
  ...
}

int main()
{
    func( "foo ");  // by your rationale, wouldn't this also call the copy ctor? 



This seems insane and wasteful to me... and I find it very hard to believe the standard dictates this. There is literally no reason for the temporary to be created in either case here.
You can try the example with function specifier explicit with using VC++.
> by your rationale, wouldn't this also call the copy ctor?
> This seems insane and wasteful to me... and I find it very hard to believe the standard dictates this.

It involves copy initialization (not copy construction).

1
2
3
4
5
6
7
String a("foo"); // direct initialization
// http://en.cppreference.com/w/cpp/language/direct_initialization

String a = "foo"; // copy initialization
// http://en.cppreference.com/w/cpp/language/copy_initialization

func( "foo" ); // copy initialization 



I stand corrected... and am completely flabbergasted.

That makes zero sense to me.
> and am completely flabbergasted.
> That makes zero sense to me.

Copy initialization is less permissive than direct initialization. That does not imply that it must be any less efficient than direct initialization.

In the above example, if there is no accessible non-explicit constructor, there would be a compile-time error. If there is one, there is no error, and the code generated is the same as in the case of direct initialization (the copy constructor is required to be accessible even though it's not used).
Last edited on
I do not understand your answers, could you try again please?
Why "abc" is a char* and not a string?

In the general sense of the word "string", it's a string. A char* is the basic way to handle strings in C. "abc" is a string literal, so therefore it's a char*.

But it's not a std::string. std::string is the STL string class. It's different from a char*, and is much more powerful (and safer) to use.

In C and C++, a string literal has the type char*, not std::string.

Edit: and I have no idea what the String type is that you have in your code, but I presume it's another class that implements a string, and so is different again from both std::string and char*.
Last edited on
@IrarI
Vlad:
Why doesn't it call the Ass.op after converting the char* to a string?


The copy assignment operator is applied to already created objects. When an object is being created a copy constructor is used. Compare.

String s1;

String s2 = s1; // the copy constructor is used

String s3;
s3 = s1; // the copy assignment operator is used.
Topic archived. No new replies allowed.