对不起基本问题,但我无法找到正确的谷歌。
#include <iostream>
#include <string>
using namespace std;
class C {
public:
C(int n) {
x = new int(n);
}
~C( ) {
delete x;
}
int getX() {return *x;}
private:
int* x;
};
void main( ) {
C obj1 = C(3);
obj1 = C(4);
cout << obj1.getX() << endl;
}
看起来它正确地进行了赋值,然后在obj1上调用析构函数,使x保留垃圾值而不是值4.如果这是有效的,为什么要这样做?
答案 0 :(得分:2)
如果有一个C类的构造函数接受一个int,那么这段代码是否有效?
C obj1(3); obj1=C(4);
假设C有operator=(C)
(默认情况下),代码有效。会发生的是,在第一行中,obj1构造为3作为构造函数的参数。然后在第二行,构造一个临时C对象,其中4作为参数,然后在obj1上调用operator=
,并将该临时对象作为参数。之后,临时对象将被破坏。
如果obj1
在分配后处于无效状态(但之前没有),则可能是C operator=
出现问题。
更新:如果x确实需要成为指针,则有三个选项:
operator=
,以便它将创建整数的副本而不是值的副本。如果在实际代码中使用指向比int大得多的东西的指针,这可能太贵了。答案 1 :(得分:2)
如果C包含指向某个东西的指针,那么你几乎总是需要实现operator =。在你的情况下,它将有这个签名
class C
{
public:
void operator=(const C& rhs)
{
// For each member in rhs, copy it to ourselves
}
// Your other member variables and methods go here...
};
答案 2 :(得分:2)
我不太了解深度,微妙的C ++来解释你遇到的问题。但是,我知道,如果您遵循您发布的代码违反的Rule of Three,确保课程的行为方式要容易得多。基本上,它声明如果你定义以下任何一个,你应该定义所有三个:
还要注意,赋值运算符实现需要正确处理将对象分配给自身的情况(所谓的“自我赋值”)。以下应该正常工作(未经测试):
#include <iostream>
#include <string>
using namespace std;
class C {
public:
C(int n) {
x = new int(n);
}
C(const C &other): C(other.getX()) { }
~C( ) {
delete x;
}
void operator=(const C &other) {
// Just assign over x. You could reallocate if you first test
// that x != other.x (the pointers, not contents). The test is
// needed to make sure the code is self-assignment-safe.
*x = *(other.x);
}
int getX() {return *x;}
private:
int* x;
};
void main( ) {
C obj1 = C(3);
obj1 = C(4);
cout << obj1.getX() << endl;
}
答案 3 :(得分:1)
新强> 发生的事情是你的析构函数已经释放了由C(4)的构造函数分配的内存。所以你从C(4)复制的指针是一个悬空指针,即它仍然指向解除分配的内存的内存位置
class C {
public:
C(int n) {
x = new int(n);
}
~C( ) {
//delete x; //Don't deallocate
}
void DeallocateX()
{
delete x;
}
int getX() {return *x;}
private:
int* x;
};
int main(int argc, char* argv[])
{
// Init with C(3)
C obj1 = C(3);
// Deallocate C(3)
obj1.DeallocateX();
// Allocate memory and store 4 with C(4) and pass the pointer over to obj1
obj1 = C(4);
// Use the value
cout << obj1.getX() << endl;
// Cleanup
obj1.DeallocateX();
return 0;
}
答案 4 :(得分:1)
明确指针的所有权! auto_ptr非常适合这个。此外,在创建本地时,不要创建C obj1 = C(3)
创建C的两个实例,并使用第二个的复制构造函数初始化第一个。
class C {
public:
C(int n) : x(new int(n)) { }
int getX(){ return *x; }
C(const C& other) : x(new int(*other.x)){}
C& operator=(const C& other) { *x = *other.x; return *this; }
private:
std::auto_ptr<int> x;
};
int main() {
C obj1(3);
obj1 = C(4);
std::cout << obj1.getX() << std::endl;
}
答案 5 :(得分:1)
基本上你正试图重新实现一个智能指针 这对于所有情况都是正确的并非易事。
请先查看标准中的可用智能指针。
基本实现(在某些情况下会失败(复制其中一个标准版本以获得更好的一个))。但这应该涵盖基础知识:
class X
{
int* data;
public:
// Destructor obvious
~X()
{
delete data;
}
// Easy constructor.
X(int x)
:data(new int(x))
{}
// Copy constructor.
// Relatively obvious just do the same as the normal construcor.
// Get the value from the rhs (copy). Note A class is a friend of
// itself and thus you can access the private members of copy without
// having to use any accessor functions like getX()
X(X const& copy)
:data(new int(copy.x))
{}
// Assignment operator
// This is an example of the copy and swap idiom. This is probably overkill
// for this trivial example but provided here to show how it is used.
X& operator=(X const& copy)
{
X tmp(copy);
this->swap(tmp);
return this;
}
// Write a swap() operator.
// Mark it is as no-throw.
void swap(X& rhs) throws()
{
std::swap(data,rhs.data);
}
};
答案 6 :(得分:0)
您何时测试obj1
的值?是在你离开范围之后吗?
在您的示例中,obj1
是一个堆栈对象。这意味着只要您离开它定义的函数,它就会被清理(析构函数被调用)。尝试在堆上分配对象:
C *obj1 = new C(3);
delete obj1;
obj1 = new C(4);