2013-08-21 3 views
0

Это, наверное, нелегко, но я немного в тупике. У меня были проблемы с моим vectors not behaving nicely, и теперь похоже, что я нашел преступника. Ниже приведена моя версия Player.Почему мой конструктор копий не работает?

class Player { 
private: 
    std::string _firstName; 
    std::string _lastName; 
public: 
    Player(std::string firstName, std::string lastName) { 
     _firstName = firstName; 
     _lastName = lastName; 
    }; 
    Player(const Player& otherPlayer) { 
     _firstName = otherPlayer._firstName.c_str(); 
     _lastName = otherPlayer._lastName.c_str(); 
     std::cout << "Created " << _firstName << " " << _lastName << std::endl; // Why doesn't _firstName and _lastName contain anything? 
    }; 
    std::string GetName() { return _firstName + " " + _lastName; }; 
}; 

int main(int argc, const char * argv[]) 
{ 

    Player player1 = Player("Bill", "Clinton"); 
    Player player2 = Player(player1); 

    std::cout << "Player: " << player2.GetName() << std::endl; 

    return 0; 
} 

Выходной сигнал является скудным Player:. Я не уверен, почему мой конструктор копий не делает то, что я хочу, чтобы это сделать, в частности, в свете рекомендаций, таких как this (комментарий Zac Howland учитывает c_str(); -part). Я нарушаю the rule of three (что, кстати, я до сих пор не полностью опустил голову)? Я был бы очень благодарен, если бы кто-нибудь мог указать мне в правильном направлении!

+1

@ Замечания Zak Howland неверны.Он описывает, как все работало ~ 10 лет назад, но (A) теперь требуется 'std :: string :: operator =', чтобы сделать глубокую копию, и (B) всегда требовалось _act like_ глубокую копию. –

+0

[Я добавил '#include ' и '#include '] (http://ideone.com/DjrNcp) – Derek

+1

На самом деле вам вообще не нужен конструктор копирования - по умолчанию он пойдет правильно. Если у вас это есть, вам не нужны вызовы 'c_str()' (они просто делают его менее надежным), и вы должны инициализировать членов, а не назначать им. Но, несмотря на это, я не вижу причин, почему он не должен работать так, как он есть. Какой результат вы получаете? –

ответ

4

Это работает для меня: http://ideone.com/aenViu

Я просто addded:

#include <iostream> 
#include <string> 

Но есть что-то я не понимаю:

_firstName = otherPlayer._firstName.c_str(); 
_lastName = otherPlayer._lastName.c_str(); 

Почему .c_str()? Вы конвертируете string в char*, чтобы присвоить его новому string?

EDIT: Из комментария, Zac Хоулэнд указал: «До C++ 11, если вы хотите, чтобы убедиться, ваша строка была скопирована (вместо подсчета ссылок), вы должны были использовать метод c_str(), чтобы заставить он копирует строку. Новый стандарт устраняет это, но если он использует старый компилятор или тот, который еще не полностью реализовал C++ 11, он обеспечит глубокую копию ».

Вобще:

_firstName = otherPlayer._firstName; 
_lastName = otherPlayer._lastName; 

И, вы действительно нужен этот конструктор копирования? По умолчанию будет делать то, что вы хотите, я думаю ...


Кроме того, вместо назначения членов:

Player(std::string firstName, std::string lastName) { 
    _firstName = firstName; 
    _lastName = lastName; 
} 

использовать член-инициализации-лист вместо:

Player(std::string firstName, std::string lastName) : 
    _firstName(std::move(firstName)), 
    _lastName(std::move(lastName)) 
{} 

В первом случае, когда вызывается конструктор по умолчанию для строки, а затем оператор присваивания строки string, определенно могут быть (небольшие) потери эффективности compa красный во второй случай, который непосредственно вызывает конструктор-копию.

Последняя вещь, когда это возможно, не передавать значения в качестве аргументов метода, передавать ссылки и даже константные ссылки, когда они не должны быть изменены:

Player(const std::string& firstName, const std::string& lastName) 
//  ^^^^^   ^   ^^^^^   ^
    : _firstName(firstName) // no move here, since args are constant references 
    , _lastName(lastName) 
{} 

Рабочая live example всего изменения.

+1

До C++ 11, если вы хотите, чтобы ваша строка была скопирована (вместо подсчета ссылок), вам пришлось использовать метод c_str(), чтобы заставить его скопировать строку. Новый стандарт устраняет это, но если он использует старый компилятор или тот, который еще не полностью реализовал C++ 11, он обеспечит глубокую копию. –

+0

@ZacHowland О, это верно! Я поставлю это в ответ! Спасибо, что указали это! –

+0

@PierreFourgeaud Я думаю, я спровоцировал вас с моим удаленным (я думал, это было неуместно после того, как я увидел, что вы используете комментарий 'std :: move()'), чтобы внести изменения об использовании 'const &'. Но теперь вы можете объяснить, пожалуйста, причину 'std :: move()' в вашем конструкторе с 'const &'? – lapk

Смежные вопросы