Есть ли явная копия - PullRequest
       16

Есть ли явная копия

2 голосов
/ 26 ноября 2010

Я ищу синтаксис, подобный следующему:

class Hugo
{
    Hugo();
    explicit Hugo( const Hugo& hugo );

    Hugo GetRandomHugo()
    {
        Hugo hugo;
        hugo.value = rand();
                                  // this would fail:
                                  //    return hugo;

        return Hugo(hugo);        // explicit copy!!
    }
};

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

Я использую GCC 4.4.5.

Большое спасибо,

Charly

Ответы [ 3 ]

5 голосов
/ 26 ноября 2010

Вы не можете: возврат по значению является неявной копией конструкции. Здесь return пытается неявно скопировать ваш явно созданный экземпляр временного.

От 8,5 / 12:

Инициализация, которая происходит в передача аргумента, функция возврата , выбрасывание исключения (15.1), обработка исключение (15.3) и заключенные в скобки списки инициализаторов (8.5.1) называется инициализацией копирования и эквивалентно форме:

T x = a;

3 голосов
/ 26 ноября 2010

Вы можете обойти это, имея явный класс HugoCopy, подобный следующему

class HugoCopy;
class Hugo {
public:
    Hugo() { ... }  
    Hugo(HugoCopy const&);
    explicit Hugo(Hugo const&) { ... }
};

struct HugoCopy { 
    HugoCopy(Hugo const& hugo) 
      :hugo(hugo)
    { }

    Hugo const& hugo;
};

Hugo::Hugo(HugoCopy const&) { ... }

Теперь применяется следующая семантика

Hugo a;
Hugo b = a; // forbidden
Hugo c(a); // allowed
Hugo d = HugoCopy(a); // allowed

Hugo f() {
  Hugo a;
  return a; // forbidden
  return HugoCopy(a); // allowed
}

В качестве альтернативы вы можете использовать функцию преобразования

class Hugo {
public:
    Hugo() { ... }  
    explicit Hugo(Hugo const&) { ... }
};

struct HugoCopy { 
    HugoCopy(Hugo const& hugo) 
      :hugo(hugo)
    { }
    operator Hugo const&() { return hugo; }

private:
    Hugo const& hugo;
};

Это опирается на тонкий угол языка C ++.Поэтому, если вы используете это, вам лучше знать, что вы делаете, или не делаете этого: сначала он вызывает функцию преобразования в HugoCopy (или, в первом случае, в конструкторе Hugo), чтобы получить Hugo/ Hugo const&, а затем direct инициализирует целевой Hugo объект с этим Hugo объектом.GCC не нравится код, но Clang и Comeau / EDG принимают его в соответствии с вышеуказанной семантикой.

1 голос
/ 26 ноября 2010
return Hugo(hugo); 

это просто создает одну дополнительную копию перед возвратом .Фактический оператор возврата затем берет эту копию и копирует ее снова .Весь смысл в конструкторе копирования заключается в том, что его можно использовать неявно, всякий раз, когда нам или компилятору требуется скопировать объект.

Если вам нужен явный синтаксис, вы можете просто добавить Clone() или Copy() функция для класса, но она не может заменить конструктор копирования.

Каждый раз, когда компилятору необходимо скопировать объект (например, при передаче его по значению в качестве параметра функции или при возврате его изфункция), для этого нужно создать копию объекта.Невозможно сделать это для компилятора, потому что вы не видите код перехода между вызывающим и вызываемым.Вы можете скопировать объект вокруг внутри вызываемой функции или за ее пределы, но у вас нет возможности скопировать его из тела вызывающего в вызывающую.Только компилятор может сделать это, и для этого ему нужно иметь возможность скопировать объект по желанию - что делается с помощью конструктора копирования.

...