【发布时间】:2021-08-12 08:34:14
【问题描述】:
我正在尝试创建自定义类型的类对象,我想添加到向量中。 是怎么做到的?
这是课程的代码和它给我带来的问题。 它自己的类按预期工作,但是在尝试将这些添加到向量时!
编辑:上传包含所有 cmets 和东西的总代码。
#ifndef TRIPLE_H
#define TRIPLE_H
#include <iostream>
#include <sstream>
#include <initializer_list>
// https://en.cppreference.com/w/cpp/memory/unique_ptr
#include <memory>
using namespace std;
template <typename S, typename T, typename R>
class Triple
{
public:
Triple();
Triple(S, T, R);
Triple(Triple &);
~Triple();
const Triple &operator=(const Triple &other);
//bool operator> (const TRIPLE &lhs, const TRIPLE &rhs);
//bool operator> (const TRIPLE &lhs);
//bool operator>(const TRIPLE &right) const;
string toString();
string getPerimeter();
int getPeri();
S* getFirst();
S getFirstvalue(); ///////////////
T* getSecond();
void set(S,T,R);
int getPairCount();
void setFirst(S);
void setSecond(T);
private:
S *first;
T *second;
R *third;
int *perimeter;
static int count_of_triples;
};
template <typename S, typename T, typename R>
int Triple<S, T, R>::count_of_triples=0;
// 0-parameter constructor
template <typename S, typename T, typename R>
Triple<S, T, R>::Triple() : first(NULL), second(NULL), third(NULL), perimeter(0)
{
//f = NULL;
//s = NULL;
count_of_triples++;
}
// 2-param constructor
template <typename S, typename T, typename R>
Triple<S, T, R>::Triple(S x, T y, R z) // : first(x), second(y), third(z), perimeter(x + y + z)
{
first = new S;
*first = x;
second = new T;
*second = y;
third = new R;
*third= y;
perimeter = new int;
//*perimeter = z;
//std::cout << "perimeter: " << (x + y + z) << end;
*perimeter = (x + y + z);
count_of_triples++;
}
template <typename S, typename T, typename R>
S Triple<S, T, R>::getFirstvalue(){
if (first!=NULL){
// if(*first == 0){
// std::cout << "error" << endl;
// }
// else{
// std::cout << "all ok" << endl;
// }
return *first;
}
else
//return NULL; // warning: converting to non-pointer type 'int' from NULL
return 0;
}
template <typename S, typename T, typename R>
string Triple<S, T, R>::toString()
{
stringstream ss;
ss<<"(";
if (first==NULL)
ss<<"NULL";
else
ss<<(*first);
ss<<",";
if (second==NULL)
ss<<"NULL";
else
ss<<(*second);
ss<<",";
if (third==NULL)
ss<<"NULL";
else
ss<<(*third);
ss<<")";
return ss.str();
}
template <typename S, typename T, typename R>
string Triple<S, T, R> ::getPerimeter(){
stringstream ss;
ss<<"(";
if (perimeter==NULL)
ss<<"NULL";
else
ss<<(*perimeter);
ss<<")";
return ss.str();
}
template <typename S, typename T, typename R>
int Triple<S, T, R> ::getPeri(){
return *perimeter;
}
template <typename S, typename T, typename R>
Triple<S, T, R> ::~Triple()
{
if(first != NULL)
delete first;
if(second != NULL)
delete second;
if(third != NULL)
delete third;
if(perimeter != NULL)
delete perimeter;
first = NULL;
second = NULL;
third = NULL;
perimeter = NULL;
count_of_triples--;
}
template <typename S, typename T, typename R>
int Triple<S, T, R>::getPairCount(){
return count_of_triples;
}
template <typename S, typename T, typename R>
void Triple<S, T, R>::set(S x, T y, R z){
if (first ==__null)
first = new S;
*first = x;
std::cout << "first:" << *first << endl;
if (second ==__null)
second = new S;
*second = y;
std::cout << "second:" << *second << endl;
if (third ==__null)
third = new R;
*third = z;
std::cout << "third:" << *third << endl;
if (perimeter ==__null)
perimeter = new int;
*perimeter = (x + y + z);
}
template <typename S, typename T, typename R>
const Triple<S, T, R> &Triple<S, T, R>::operator=(const Triple<S, T, R> &other){
}
template <typename S, typename T, typename R>
bool operator>(Triple<S, T, R> &lhs, Triple<S, T, R> &rhs){
return lhs.getPeri() > rhs.getPeri();
}
template <typename S, typename T, typename R>
bool operator<(Triple<S, T, R> &lhs, Triple<S, T, R> &rhs){
return lhs.getPeri() < rhs.getPeri();
}
#endif // TRIPLE_H
主要:
#include <iostream>
#include <vector>
#include <algorithm>
//#include <utility>
#include "Triple.h"
typedef vector<Triple<int, int, int>> triVector;
int main(){
Triple<int, int, int> triple;// {1,2,3};
triple.set(1,2,3);
std::cout << " ***** " << triple.toString() << endl;
std::cout << "get perimeter " << triple.getPerimeter() << endl;
std::cout << "get count " << triple.getPairCount() << endl;
Triple<int, int, int> *triple2 = new Triple<int, int, int>(1,2,5);
//TRIPLE<int, int, int> *triple2 = new TRIPLE<int, int, int>({1,2,1});
std::cout << " ***** " << triple2->toString() << endl;
std::cout << "get perimeter " << triple2->getPerimeter() << endl;
std::cout << "get count " << triple2->getPairCount() << endl;
Triple<int, int, int> triple3;// {1,2,3};
triple3.set(1,2,2);
if(triple < *triple2){
std::cout << "true" << endl;
}
else{
std::cout << "not true" << endl;
}
std::cout << triple.getFirstvalue() << endl;
triVector temp;
temp.push_back(*triple2);
// temp.push_back(triple);
// temp.push_back(triple3);
for(auto i : temp){
std::cout << "peri: " << i.getPeri() << endl;
}
std::cout << "-----------------------------------------" << endl;
//sort(temp.begin(), temp.end());
// for(auto i : temp){
// std::cout << "peri: " << i.getPeri() << endl;
// }
// std::cout << "-----------------------------------------" << endl;
return 0;
}
错误:
/usr/include/c++/9/ext/new_allocator.h:145: error: binding reference of type ‘Triple<int, int, int>&’ to ‘const Triple<int, int, int>’ discards qualifiers
In file included from /usr/include/x86_64-linux-gnu/c++/9/bits/c++allocator.h:33,
from /usr/include/c++/9/bits/allocator.h:46,
from /usr/include/c++/9/string:41,
from /usr/include/c++/9/bits/locale_classes.h:40,
from /usr/include/c++/9/bits/ios_base.h:41,
from /usr/include/c++/9/ios:42,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from ../Pair_template/main.cpp:14:
/usr/include/c++/9/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Triple<int, int, int>; _Args = {const Triple<int, int, int>&}; _Tp = Triple<int, int, int>]’:
/usr/include/c++/9/bits/alloc_traits.h:482:2: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = Triple<int, int, int>; _Args = {const Triple<int, int, int>&}; _Tp = Triple<int, int, int>; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<Triple<int, int, int> >]’
/usr/include/c++/9/bits/stl_vector.h:1189:30: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Triple<int, int, int>; _Alloc = std::allocator<Triple<int, int, int> >; std::vector<_Tp, _Alloc>::value_type = Triple<int, int, int>]’
../Pair_template/main.cpp:91:28: required from here
/usr/include/c++/9/ext/new_allocator.h:145:20: error: binding reference of type ‘Triple<int, int, int>&’ to ‘const Triple<int, int, int>’ discards qualifiers
145 | noexcept(noexcept(::new((void *)__p)
| ^~~~~~~~~~~~~~~~~~
146 | _Up(std::forward<_Args>(__args)...)))
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
【问题讨论】:
-
因为vector重新分配了它的内容,vector的内容必须符合Rule Of 3。显示的自定义模板不是。您必须在模板类中实现正确的复制构造函数和赋值运算符。
-
复制构造函数通常不会修改其参数。
-
错字
Triple(Triple &) ~Triple();?接下来的两行。我们怎么知道这是我们应该查看的真实代码? "...debugger 停止在:~Triple()..." 不,是编译器说它不能编译程序。 -
我很想在格式修复期间修复已发布代码中明显的语法错误,即在 dtor 之前声明非标准复制ctor之后缺少的
;。我决定不去。 SO 九年了,我仍然感到困惑,复制/粘贴所谓的问题重现代码如何以某种方式引入“错别字”。小精灵。 -
Using std::tuple。您当前的代码有潜在的内存泄漏和各种其他问题 - 不妨向您展示一些可以实现您正在尝试编码的东西,但要简单得多。