为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
Why does a member of ostringstream type in class cause "call to implicity deleted copy-constructor" error?
我已经隔离了一个问题"调用隐式删除的复制构造函数";在声明类的成员时使用ostrinstream类型的编译错误。在下面的示例中,定义了示例的Reading类的对象的STL列表。在调用push_back时,编译器搜索复制构造函数,但编译失败,这似乎是因为Readings的复制构造函数已被隐式删除。
当我注释掉引用payloadString的两行时,程序就会编译。
我想我的问题可能是ostringstream是引用类型,正如这里所解释的:
https://en.cppreference.com/w/cpp/language/copy_constructor"T具有右值引用类型的数据成员"被引用为隐式删除复制构造函数的可能原因之一。
Q。有人能证实我上面关于奥斯特林斯特流是导致问题的参考类型的假设是否正确吗?
我使用ostringstream的原因在这个人为的例子中并不明显。也许我需要找到另一种方法来处理这个字符串,但有人能建议一种在这里有效的方法吗?
// testing a problem where ostringstream causes implicitly deleted copy constructor
//
// using ostringstream in a class definition seems to cause implicit deletion of the copy constructor
#include <iostream>
#include <sstream>
#include <list>
#include <string>
using namespace std;
class Reading {
public:
double elevation;
std::ostringstream payloadString; // using ostringstream here causes implicit deletion of the copy constructor
double speed;
// constructors and member functions
Reading(); // initialisation constructor declaration
private:
};
Reading::Reading(): // initialisation constructor definition
elevation(0.0),
payloadString("_null_null_"), // commenting out this line and the previous definition in the class makes the problem go away
speed(0.0)
{}
int main()
{
std::list<Reading> readingsList; // a list of readings
Reading fakeReading; // just initialises with dummy data
// this line is what causes the compiler to complain about implicitly deleted copy constructors
readingsList.push_back(fakeReading);
return 0;
}
每个类都有一个隐式声明的复制构造函数,如果您没有声明,但只有当每个数据成员和继承的类型都可以被复制构造时。std::ostringstream
没有复制构造函数,因此编译器无法为Reading
生成复制构造函数。
如果您可以确定一种以有意义的方式构造Reading::payloadString
的方法,那么您可以自己定义一个复制构造函数。例如,您可以执行以下操作:
Reading(Reading const & other) :
elevation{other.elevation},
payloadString{other.payloadString.str()},
speed{other.speed} { }
注意,这会复制other.payloadString
中包含的字符串值,但不会复制流的其他方面,例如其各种输出模式或输出位置。这对你的案子来说可能已经足够了。
如果定义此构造函数,则可能还需要定义复制赋值操作,因为同样的原因,该操作无法自动生成。您可以模仿上面复制构造函数的语义:
Reading & operator=(Reading const & other) {
elevation = other.elevation;
payloadString = std::ostringstream{other.payloadString.str()};
speed = other.speed;
return *this;
}
请注意,std::ostringstream
可以移动,这意味着编译器将自动为Reading
生成一个移动构造函数和一个移动赋值运算符。因此,您可以从fakeReading
:中移动构造列表元素
readingsList.emplace_back(std::move(fakeReading));
如果你选择实现复制构造函数/赋值,那么编译器将而不是为你生成移动构造函数/赋值。你必须明确地告诉编译器生成它们:
Reading(Reading &&) = default;
Reading & operator=(Reading &&) = default;
感谢cdhowie提供的详细而有用的答案。
我采纳了您的建议,并使用template_back实现了我的示例。下面的代码现在看起来工作得很好。
// testing a problem where ostringstream causes implicitly deleted copy constructor
//
// using ostringstream in a class definition seems to cause implicit deletion of the copy constructor
#include <iostream>
#include <sstream>
#include <list>
#include <string>
using namespace std;
class Reading {
public:
double elevation;
std::ostringstream payloadString; // using ostringstream here causes implicit deletion of the copy constructor
double speed;
// constructors and member functions
Reading(); // initialisation constructor declaration
private:
};
Reading::Reading(): // initialisation constructor definition
elevation(0.0),
payloadString("_null_null_"), // commenting out this line and the previous definition in the class makes the problem go away
speed(0.0)
{}
int main()
{
std::list<Reading> readingsList; // a list of readings
Reading fakeReading1; // just initialises with dummy data
Reading fakeReading2; // just initialises with dummy data
Reading fakeReading3; // just initialises with dummy data
fakeReading1.elevation = 1.0;
fakeReading2.elevation = 2.0;
fakeReading3.elevation = 4.0;
fakeReading1.payloadString.str("reading1 payload");
fakeReading3.payloadString.str("reading3 payload");
// this line is what causes the compiler to complain about implicitly deleted copy constructors
readingsList.emplace_back(std::move(fakeReading1));
readingsList.emplace_back(std::move(fakeReading2));
readingsList.emplace_back(std::move(fakeReading3));
for (auto const &v : readingsList){
cout << "elevation = " << v.elevation << endl;
cout << "speed = " << v.speed << endl;
cout << "payloadString = " << v.payloadString.str() << endl << endl;
}
return 0;
}
它产生以下输出,正确且符合预期:
elevation = 1
speed = 0
payloadString = reading1 payload
elevation = 2
speed = 0
payloadString = _null_null_
elevation = 4
speed = 0
payloadString = reading3 payload
Process returned 0 (0x0) execution time : 0.023 s
Press any key to continue.
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 函数何时会在c++中包含stack_Unwind_Resume调用