在复制构造函数中用垃圾值初始化的变量
Variable initialized with garbage value in copy constructor
在我的 comp sci class 中,我们正在制作矢量 class。我被卡住了,因为我的复制构造函数正在用垃圾值初始化我的 'limit' 变量,我不明白为什么。
这是我的主要内容:
myStringVector v1 {"a", "b", "c"};
std::cout << "make it here?" << std::endl;
myStringVector v2 = v1;
std::cout << v1[0] << v1[1] << v1[2] << std::endl;
std::cout << v2[0] << v2[1] << v2[2] << std::endl;
assert(v1 == v2);
std::cout << "Passed copy ctor" << std::endl;
这是一个构造函数,它接受一个 initializer_list
myStringVector::myStringVector(std::initializer_list<myString> list){
this->reserve(list.size());
for(int i = 0; i < limit-1; i++){
construct(first+i, list.begin()[i]);
}
}
这里是拷贝构造函数
myStringVector::myStringVector(const myStringVector& data){
reserve((data.limit)-1);
for(int i = 0; i < data.limit-1; i++){
construct(&first+i, data.first+i);
}
}
这是储备的样子
void myStringVector::reserve(int n){
this->first = allocate<myString>(n);
this->last = first+n;
this->limit = n+1;
}
我在 main 中的断言失败了,因为我重载了 == 运算符以首先检查限制是否相等。如果不是,则函数 return 为假。该函数在那之后继续,但断言失败,因为我将我的 v1 设置为 4,这是正确的,然后我的 v2 是一些没有意义的大数字。
我已经尝试重写我的复制构造函数以直接初始化 class 的成员而不使用保留,但它仍然不起作用。它仍然在为 limit 分配垃圾值。其余部分工作正常。
这是 main 输出的内容...
能到这里吗?
abc
abc
4 7500072
断言失败:v1 == v2,文件 myCodeTres.cpp,第 58 行
我觉得我已经尝试了所有我能想到的方法来尝试解决这个问题,但没有任何效果。对我有什么建议吗?
谢谢。
更新:这些是我在省略 & 符号时遇到的编译器错误。
在 myCodeTres.cpp 包含的文件中:20:
myMemory.hpp:在 'T* construct(T*, Args&& ...) [with T = myString; Args = {myString*}]' 的实例化中:
myStringVector.cpp:25:36: 从这里需要
myMemory.hpp:61:10: 错误:没有匹配函数来调用 'myString::myString(myString*)'
61 | return new (p) T(std::forward(args)...);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**然后在编译器屏幕上出现一些蓝色的奇怪错误**
在 myCodeTres.cpp 包含的文件中:23:
myString.cpp:42:1: 注:候选人:'myString::myString(myString&&)'
42 | myString::myString(myString&& move) : strLength(strlen(move.stringVar)) //移动构造函数以从中移动内容
| ^~~~~~~~
myString.cpp:42:31:注意:参数 1 没有从 'myString*' 到 'myString&&' 的已知转换
42 | myString::myString(myString&& move) : strLength(strlen(move.stringVar)) //移动构造函数以从中移动内容
| ~~~~~~~~~~~^~~~
myString.cpp:32:1: 注:候选人:'myString::myString(const myString&)'
32 | myString::myString(const myString& strToCpy) : strLength(strlen(strToCpy.stringVar)) //删除旧元素的复制构造函数
| ^~~~~~~~
myString.cpp:32:36:注意:参数 1 没有从 'myString*' 到 'const myString&' 的已知转换
32 | myString::myString(const myString& strToCpy) : strLength(strlen(strToCpy.stringVar)) //删除旧元素的复制构造函数
| ~~~~~~~~~~~~~~~~^~~~~~~~
在 myCodeTres.cpp:23 包含的文件中:
myString.cpp:23:1: 注:候选人:'myString::myString(const char*, std::size_t)'
23 | myString::myString(const char* cPnt, std::size_t size) : strLength(size) // 获取大小和 const ptr 到 char 的构造函数
| ^~~~~~~~
myString.cpp:23:1: 注意:候选人需要 2 个参数,提供 1 个
myString.cpp:14:1: 注:候选人:'myString::myString(const char*)'
14 | myString::myString(const char* cPnt) : strLength(strlen(cPnt)) //构造函数以将给定的 const ptr 初始化为 char。
| ^~~~~~~~
myString.cpp:14:32:注意:参数 1 没有从 'myString*' 到 'const char*' 的已知转换
14 | myString::myString(const char* cPnt) : strLength(strlen(cPnt)) //构造函数以将给定的 const ptr 初始化为 char。
| ~~~~~~~~~~~~^~~~
myString.cpp:8:1: 注:候选人:'myString::myString()'
8 | myString::myString() //默认构造函数:初始化空字符串。
| ^~~~~~~~
myString.cpp:8:1: 注意:候选人需要 0 个参数,提供 1 个
更新:整个class定义
#ifndef MYSTRINGVECTOR_HPP
#define MYSTRINGVECTOR_HPP
#include "myString.hpp"
#include <initializer_list>
class myStringVector{
private:
myString *first, *last;
int limit = 0;
public:
void reserve(int); //allocate memory at 'first' for n myString's
myStringVector(); //call to reserve(0)
myStringVector(std::initializer_list<myString>);
myStringVector(const myStringVector&);
bool empty();
bool operator==(const myStringVector&);
myString operator[](int);
int getSize() const;
};
#endif //MYSTRINGVECTOR_HPP_INCLUDED
.cpp 文件
#include "myStringVector.hpp"
#include "myMemory.hpp"
#include <initializer_list>
void myStringVector::reserve(int n){
this->first = allocate<myString>(n);
this->last = first+n;
this->limit = n+1;
}
myStringVector::myStringVector(){
this->reserve(0);
}
myStringVector::myStringVector(std::initializer_list<myString> list){
this->reserve(list.size());
for(int i = 0; i < limit-1; i++){
construct(first+i, list.begin()[i]);
}
}
myStringVector::myStringVector(const myStringVector& data){
reserve((data.limit)-1);
for(int i = 0; i < data.limit-1; i++){
construct(first+i, data.first+i);
}
}
bool myStringVector::empty(){
return (limit-1 == 0);
}
bool myStringVector::operator==(const myStringVector& data){
std::cout << limit << " " << data.limit << std::endl;
if(this->limit != data.limit)
return 0;
for(int i = 0; i < limit; i++){
if(*(first+i) != *(data.first+i))
return 0;
}
return 1;
}
myString myStringVector::operator[](int index){
return *(first+index);
}
int myStringVector::getSize() const{
return limit-1;
}
格式化有点不对劲,因为将代码上传到 Whosebug 非常乏味。
复制构造函数中的简单错误
construct(&first+i, data.first+i);
应该是
construct(first+i, data.first+i);
编辑
这来自初始化列表构造函数。
construct(first+i, list.begin()[i]);
现在仔细想想这里的类型。第一个参数很简单,它是指向 myString 的指针,即 myString*
。第二个有点复杂,因为您必须理解 std::initializer_list
,但如果您按照它进行操作,它就是对 myString 的 const 引用,即 const myString&
。现在这很好,因为 construct
是这样定义的
template <class T>
void construct(T* first, const T& second);
即对于某些类型 T
它的第一个参数是指向该类型的指针,第二个参数是对该类型的常量引用。
现在看看第二次使用的类型construct
(不编译的那个)
construct(first+i, data.first+i);
第一个参数是myString*
,第二个参数是const myString*
。两点指点!这就是它不编译的原因!您的解决方案是向第一个参数添加一个额外的指针。
的类型
construct(&first+i, data.first+i);
是 myString**
和 const myString*
。编译是因为你在左边有一个双指针,在右边有一个指针,但这意味着你正在构造指向 myString 而不是 myString 对象的指针,这不是你想要的。
您应该做的是从第二个参数中删除 指针,而不是向第一个参数添加额外的指针。换句话说,正确的代码是这个
construct(first+i, data.first[i]);
现在第一个参数的类型为 myString*
,第二个参数的类型为 const myString&
。与其他构造函数完全相同。
试试这个改变,让我知道它是怎么回事。
在我的 comp sci class 中,我们正在制作矢量 class。我被卡住了,因为我的复制构造函数正在用垃圾值初始化我的 'limit' 变量,我不明白为什么。
这是我的主要内容:
myStringVector v1 {"a", "b", "c"};
std::cout << "make it here?" << std::endl;
myStringVector v2 = v1;
std::cout << v1[0] << v1[1] << v1[2] << std::endl;
std::cout << v2[0] << v2[1] << v2[2] << std::endl;
assert(v1 == v2);
std::cout << "Passed copy ctor" << std::endl;
这是一个构造函数,它接受一个 initializer_list
myStringVector::myStringVector(std::initializer_list<myString> list){
this->reserve(list.size());
for(int i = 0; i < limit-1; i++){
construct(first+i, list.begin()[i]);
}
}
这里是拷贝构造函数
myStringVector::myStringVector(const myStringVector& data){
reserve((data.limit)-1);
for(int i = 0; i < data.limit-1; i++){
construct(&first+i, data.first+i);
}
}
这是储备的样子
void myStringVector::reserve(int n){
this->first = allocate<myString>(n);
this->last = first+n;
this->limit = n+1;
}
我在 main 中的断言失败了,因为我重载了 == 运算符以首先检查限制是否相等。如果不是,则函数 return 为假。该函数在那之后继续,但断言失败,因为我将我的 v1 设置为 4,这是正确的,然后我的 v2 是一些没有意义的大数字。
我已经尝试重写我的复制构造函数以直接初始化 class 的成员而不使用保留,但它仍然不起作用。它仍然在为 limit 分配垃圾值。其余部分工作正常。
这是 main 输出的内容...
能到这里吗?
abc
abc
4 7500072
断言失败:v1 == v2,文件 myCodeTres.cpp,第 58 行
我觉得我已经尝试了所有我能想到的方法来尝试解决这个问题,但没有任何效果。对我有什么建议吗?
谢谢。
更新:这些是我在省略 & 符号时遇到的编译器错误。
在 myCodeTres.cpp 包含的文件中:20: myMemory.hpp:在 'T* construct(T*, Args&& ...) [with T = myString; Args = {myString*}]' 的实例化中: myStringVector.cpp:25:36: 从这里需要 myMemory.hpp:61:10: 错误:没有匹配函数来调用 'myString::myString(myString*)' 61 | return new (p) T(std::forward(args)...); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**然后在编译器屏幕上出现一些蓝色的奇怪错误**
在 myCodeTres.cpp 包含的文件中:23: myString.cpp:42:1: 注:候选人:'myString::myString(myString&&)' 42 | myString::myString(myString&& move) : strLength(strlen(move.stringVar)) //移动构造函数以从中移动内容 | ^~~~~~~~ myString.cpp:42:31:注意:参数 1 没有从 'myString*' 到 'myString&&' 的已知转换 42 | myString::myString(myString&& move) : strLength(strlen(move.stringVar)) //移动构造函数以从中移动内容 | ~~~~~~~~~~~^~~~ myString.cpp:32:1: 注:候选人:'myString::myString(const myString&)' 32 | myString::myString(const myString& strToCpy) : strLength(strlen(strToCpy.stringVar)) //删除旧元素的复制构造函数 | ^~~~~~~~ myString.cpp:32:36:注意:参数 1 没有从 'myString*' 到 'const myString&' 的已知转换 32 | myString::myString(const myString& strToCpy) : strLength(strlen(strToCpy.stringVar)) //删除旧元素的复制构造函数 | ~~~~~~~~~~~~~~~~^~~~~~~~ 在 myCodeTres.cpp:23 包含的文件中: myString.cpp:23:1: 注:候选人:'myString::myString(const char*, std::size_t)' 23 | myString::myString(const char* cPnt, std::size_t size) : strLength(size) // 获取大小和 const ptr 到 char 的构造函数 | ^~~~~~~~ myString.cpp:23:1: 注意:候选人需要 2 个参数,提供 1 个 myString.cpp:14:1: 注:候选人:'myString::myString(const char*)' 14 | myString::myString(const char* cPnt) : strLength(strlen(cPnt)) //构造函数以将给定的 const ptr 初始化为 char。 | ^~~~~~~~ myString.cpp:14:32:注意:参数 1 没有从 'myString*' 到 'const char*' 的已知转换 14 | myString::myString(const char* cPnt) : strLength(strlen(cPnt)) //构造函数以将给定的 const ptr 初始化为 char。 | ~~~~~~~~~~~~^~~~ myString.cpp:8:1: 注:候选人:'myString::myString()' 8 | myString::myString() //默认构造函数:初始化空字符串。 | ^~~~~~~~ myString.cpp:8:1: 注意:候选人需要 0 个参数,提供 1 个
更新:整个class定义
#ifndef MYSTRINGVECTOR_HPP
#define MYSTRINGVECTOR_HPP
#include "myString.hpp"
#include <initializer_list>
class myStringVector{
private:
myString *first, *last;
int limit = 0;
public:
void reserve(int); //allocate memory at 'first' for n myString's
myStringVector(); //call to reserve(0)
myStringVector(std::initializer_list<myString>);
myStringVector(const myStringVector&);
bool empty();
bool operator==(const myStringVector&);
myString operator[](int);
int getSize() const;
};
#endif //MYSTRINGVECTOR_HPP_INCLUDED
.cpp 文件
#include "myStringVector.hpp"
#include "myMemory.hpp"
#include <initializer_list>
void myStringVector::reserve(int n){
this->first = allocate<myString>(n);
this->last = first+n;
this->limit = n+1;
}
myStringVector::myStringVector(){
this->reserve(0);
}
myStringVector::myStringVector(std::initializer_list<myString> list){
this->reserve(list.size());
for(int i = 0; i < limit-1; i++){
construct(first+i, list.begin()[i]);
}
}
myStringVector::myStringVector(const myStringVector& data){
reserve((data.limit)-1);
for(int i = 0; i < data.limit-1; i++){
construct(first+i, data.first+i);
}
}
bool myStringVector::empty(){
return (limit-1 == 0);
}
bool myStringVector::operator==(const myStringVector& data){
std::cout << limit << " " << data.limit << std::endl;
if(this->limit != data.limit)
return 0;
for(int i = 0; i < limit; i++){
if(*(first+i) != *(data.first+i))
return 0;
}
return 1;
}
myString myStringVector::operator[](int index){
return *(first+index);
}
int myStringVector::getSize() const{
return limit-1;
}
格式化有点不对劲,因为将代码上传到 Whosebug 非常乏味。
复制构造函数中的简单错误
construct(&first+i, data.first+i);
应该是
construct(first+i, data.first+i);
编辑
这来自初始化列表构造函数。
construct(first+i, list.begin()[i]);
现在仔细想想这里的类型。第一个参数很简单,它是指向 myString 的指针,即 myString*
。第二个有点复杂,因为您必须理解 std::initializer_list
,但如果您按照它进行操作,它就是对 myString 的 const 引用,即 const myString&
。现在这很好,因为 construct
是这样定义的
template <class T>
void construct(T* first, const T& second);
即对于某些类型 T
它的第一个参数是指向该类型的指针,第二个参数是对该类型的常量引用。
现在看看第二次使用的类型construct
(不编译的那个)
construct(first+i, data.first+i);
第一个参数是myString*
,第二个参数是const myString*
。两点指点!这就是它不编译的原因!您的解决方案是向第一个参数添加一个额外的指针。
construct(&first+i, data.first+i);
是 myString**
和 const myString*
。编译是因为你在左边有一个双指针,在右边有一个指针,但这意味着你正在构造指向 myString 而不是 myString 对象的指针,这不是你想要的。
您应该做的是从第二个参数中删除 指针,而不是向第一个参数添加额外的指针。换句话说,正确的代码是这个
construct(first+i, data.first[i]);
现在第一个参数的类型为 myString*
,第二个参数的类型为 const myString&
。与其他构造函数完全相同。
试试这个改变,让我知道它是怎么回事。