以下代码在clang ++ - 2.9和g ++ - 4.6上编译(没有警告)。但是,g ++二进制文件Seg Faults,而clang ++二进制文件按预期运行。
重载[]时,通过指针访问模板类数据成员的正确方法是什么?
以下是代码:
#include <iostream>
template <typename T>
class A {
private:
T val1;
T val2;
public:
T& getVal1() { return val1; }
void setVal1(T aVal) { val1 = aVal; }
T& getVal2() { return val2; }
void setVal2(T aVal) { val2 = aVal; }
};
template <typename T>
class B {
private:
A<T>* aPtr;
public:
A<T>* getAPtr() { return aPtr; }
T& operator[](const int& key) {
if(key == 0) { T& res = getAPtr()->getVal1();
return res; }
else { T& res = getAPtr()->getVal2();
return res; }
}
};
int main()
{
B<int> foo;
foo[0] = 1;
int x = foo[0];
std::cout << foo[0] << " " << x << std::endl; // 1 1
}
答案 0 :(得分:0)
您正在返回对局部变量(res)的引用。从operator []返回后,引用无效。它可能会被其他东西覆盖。真正发生的是未定义:这就是允许编译器吃掉你的孩子或长胡子的原因:未定义的行为
您可能希望按值返回。
由于您有一个setter,因此您不需要参考:在 http://ideone.com/oxslQ
中查看解决方案注意:aPtr
未初始化时存在另一个问题。我为此提出了一个简单的构造函数。 _您可能希望从其他地方 OR 初始化
#include <iostream>
template <typename T>
class A
{
private:
T val1;
T val2;
public:
T getVal1()
{
return val1;
}
void setVal1(T aVal)
{
val1 = aVal;
}
T getVal2()
{
return val2;
}
void setVal2(T aVal)
{
val2 = aVal;
}
};
template <typename T>
class B
{
private:
A<T>* aPtr;
B(const B&); // TODO , disallow for now
B& operator=(const B&); // TODO , disallow for now
public:
B() : aPtr(new A<T>()) {}
~B() { delete aPtr; }
A<T>* getAPtr()
{
return aPtr;
}
T operator[](const int& key)
{
if(key == 0)
{
T res = getAPtr()->getVal1();
return res;
}
else
{
T res = getAPtr()->getVal2();
return res;
}
}
};
int main()
{
B<int> foo;
foo.getAPtr()->setVal1(1);
int x = foo[0];
std::cout << foo[0] << " " << x << std::endl; // 1 1
}
答案 1 :(得分:0)
如果你想通过ref返回,那么你的A :: getValX()函数也应该由ref返回,而你在B ::运算符中的res
变量也应该是T&amp;而不是T:
#include <iostream>
template <typename T>
class A {
private:
T val1;
T val2;
public:
T& getVal1() { return val1; }
void setVal1(T aVal) { val1 = aVal; }
T& getVal2() { return val2; }
void setVal2(T aVal) { val2 = aVal; }
};
template <typename T>
class B {
private:
A<T>* aPtr;
public:
A<T>* getAPtr() { return aPtr; }
T& operator[](const int& key) {
if(key == 0) { T& res = getAPtr()->getVal1();
return res; }
else { T& res = getAPtr()->getVal2();
return res; }
}
};
int main()
{
B<int> foo;
foo[0] = 1;
int x = foo[0];
std::cout << foo[0] << " " << x << std::endl; // 1 1
}
(注意它在运行时仍然会崩溃,因为aPtr没有在任何地方初始化。)
您的原始代码返回对局部变量res的引用,而不是您可能想要的A :: val1 / A :: val2。如果res是非引用变量,那么它将是val1 / val2值的简单 copy ,它仅对声明它的作用域(在本例中为函数)内有效。所以你需要一个参考。