2013-03-26 3 views
4

Не мог бы кто-нибудь рассказать мне, почему это не работает? У меня создалось впечатление, что C++ автоматически передает ссылку на результат функции return-by-value на конструктор, но он жалуется, что никакой соответствующий оператор не может быть найден.C++ оператор не найден

class bucket_string { 
     public: 
      bucket_string(); 
      bucket_string(bucket_string & rhs); 
      bucket_string & operator=(bucket_string & rhs); 
      virtual ~bucket_string(); 

      bucket_string substr(iterator start, iterator end){ 
         bucket_string b(str); 
         return b; 
        } 
}; 



bucket_string bs("the quick brown fox jumps over the lazy dog"); 
bucket_string bs1 = bs.substr(bs.begin(), bs.end()); 

возвращает следующее сообщение об ошибке:

error: no matching function for call to ‘bucket_string::bucket_string(bucket_string)’ 
note: candidates are: bucket_string::bucket_string(bucket_string&) 
     bucket_string::bucket_string() 
+4

Я удивлен, что вы не получите сообщение об ошибке для 'bucket_string :: bucket_string (const char *)'. Это ваш полный код? Также, где объявлен 'iterator'? –

+0

Нет, это не так - я удалил большинство из них, чтобы было легче читать и отвечать на мой вопрос :-) – Supremacy

+0

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

ответ

7

В C++, временные значения не может быть связаны с неконстантными ссылками.

Функция bucket_string substr(iterator start, iterator end) возвращает временный, и ваш оператор-конструктор/присваивание принимает неконстантную ссылку в качестве параметра, следовательно, вашу проблему.

Таким образом, вам необходимо добавить отсутствующий спецификатор const в свой конструктор и оператор присваивания. Как так:

bucket_string(const bucket_string& rhs); 
bucket_string& operator=(const bucket_string& rhs); 

Вот interesting discussion на эту тему для лучшего понимания.

На стороне примечания, и если C++ 11 является опцией, вы также можете сделать свой класс подвижным. Это позволит перевести внутренние ресурсы вашего временного объекта в другой экземпляр. Нам не хватает контекста, чтобы сказать, хорошо ли это в вашей ситуации.

Вы бы тогда реализовать эти методы:

bucket_string(bucket_string&& other); 
bucket_string& operator=(bucket_string&& other); 
+0

@Tushar: Hum ... что? – ereOn

+0

Этот ответ в этой ссылке сделал это несколько яснее, спасибо. – Supremacy

+0

@ Превосходство: Рад, что я мог бы помочь. – ereOn

6

Положите несколько const.

bucket_string(const bucket_string & rhs); 
       ^^^^^ 
bucket_string & operator=(const bucket_string & rhs); 
          ^^^^^ 

Вы передаете временные значения const конструктору. Компилятор ищет конструктора, который accpets const ссылки:

bucket_string bs("the quick brown fox jumps over the lazy dog"); 
+7

Вы действительно должны объяснить, почему нужно «поместить некоторый const». Речь идет не о «передаче значений const». – juanchopanza

+1

Стоит упомянуть, что временные лица не могут быть связаны с неконстантными ссылками. – ereOn

+0

точно, «положить какой-нибудь контр-где-нибудь, может быть, может помочь» – 4pie0

1

Код перемешивает значения и ссылки семантику таким образом, что не работает. substr возвращает значение по значению, но конструктор принимает параметр с помощью неконстантной ссылки. Будучи непостоянным, указывает, что параметр будет рассматриваться как модифицируемый объект, а не чистое значение. Язык запрещает использование ссылок таким образом. Настройте оператор присваивания, поэтому он не может изменить свой аргумент:

 bucket_string & operator=(bucket_string const & rhs); 

Это работает, потому что C++ позволит временный объект (например, возвращаемое значение функции), чтобы пропустить через const ссылки.

Если вы действительно хотите изменить источник операции присваивания, то C++ предлагает решение в ссылках rvalue. Вместо const & используйте &&. Но назначение больше не будет идемпотентным, поэтому его можно было бы называть назначением перемещения, и вам понадобится альтернативный синтаксис при использовании , а не - временные объекты.

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