Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在初始化对象之前在对象上运行的方法? #包括 使用名称空间std; 福班 { 公众: Foo():已初始化(0) { cout_C++_Initialization - Fatal编程技术网

C++ 在初始化对象之前在对象上运行的方法? #包括 使用名称空间std; 福班 { 公众: Foo():已初始化(0) { cout

C++ 在初始化对象之前在对象上运行的方法? #包括 使用名称空间std; 福班 { 公众: Foo():已初始化(0) { cout,c++,initialization,C++,Initialization,是的,它是在一个尚未构造的对象上调用函数,这是一种未定义的行为。您无法可靠地检测到它。我认为您也不应该尝试检测它。与在一个已删除的对象上调用函数相比,这并不是偶然发生的事情。尝试捕获所有可能的mISTACK几乎是不可能的。声明的名称在其初始化器中已经可见,用于其他有用的目的。 #include <iostream> using namespace std; class Foo { public: Foo(): initialised(0) { cout <<

是的,它是在一个尚未构造的对象上调用函数,这是一种未定义的行为。您无法可靠地检测到它。我认为您也不应该尝试检测它。与在一个已删除的对象上调用函数相比,这并不是偶然发生的事情。尝试捕获所有可能的mISTACK几乎是不可能的。声明的名称在其初始化器中已经可见,用于其他有用的目的。
#include <iostream>
using namespace std;

class Foo
{

public:

 Foo(): initialised(0)
 {
  cout << "Foo() gets called AFTER test() ?!" << endl;
 };

 Foo test()
 {
  cout << "initialised= " << initialised << " ?! - ";
  cout << "but I expect it to be 0 from the 'initialised(0)' initialiser on Foo()" << endl;
  cout << "this method test() is clearly working on an uninitialised object ?!" << endl;
  return Foo();
 }

 ~Foo()
 {};

private:

 int initialised;

};


int main()
{

 //SURE this is bad coding but it compiles and runs
 //I want my class to DETECT and THROW an error to prevent this type of coding
 //in other words how to catch it at run time and throw "not initialised" or something

 Foo foo=foo.test();

}

是C语言编程中常用的一个习语,它仍然在C++中工作。 就个人而言,我喜欢Herb Sutter关于空引用(同样无效)的文章。要点是,不要试图避免语言明确禁止的情况,尤其是在一般情况下无法可靠诊断的情况。随着时间的推移,您将获得错误的安全性,这将变得非常危险。相反,应以某种方式培训您对语言和设计接口的理解(避免原始指针,…)这减少了犯错误的机会

<>在C++中,同样地,在C中,很多情况并没有明确禁止,而是没有定义。部分原因是一些事情很难有效地诊断,部分是因为未定义的行为允许实现设计替代行为,而不是完全忽略它——这通常被现有的COMPI使用。莱勒斯


例如,在上面的例子中,任何实现都可以自由抛出异常。还有其他一些情况同样是未定义的行为,对于实现来说更难有效地诊断:在构建不同转换单元中的对象之前访问它就是这样一个例子,这就是所谓的static初始化命令失败。

是的,它正在对尚未构造的对象调用函数,这是未定义的行为。您无法可靠地检测到它。我认为您也不应该尝试检测它。与对已删除的对象调用函数相比,这并不是偶然发生的。尝试捕获每一个可能发生的错误几乎是不可能的。声明的名称在其初始化器中已经可见,用于其他有用的目的。请考虑:

#include <iostream>
using namespace std;

class Foo
{

public:

 Foo(): initialised(0)
 {
  cout << "Foo() gets called AFTER test() ?!" << endl;
 };

 Foo test()
 {
  cout << "initialised= " << initialised << " ?! - ";
  cout << "but I expect it to be 0 from the 'initialised(0)' initialiser on Foo()" << endl;
  cout << "this method test() is clearly working on an uninitialised object ?!" << endl;
  return Foo();
 }

 ~Foo()
 {};

private:

 int initialised;

};


int main()
{

 //SURE this is bad coding but it compiles and runs
 //I want my class to DETECT and THROW an error to prevent this type of coding
 //in other words how to catch it at run time and throw "not initialised" or something

 Foo foo=foo.test();

}

是C语言编程中常用的一个习语,它仍然在C++中工作。 就个人而言,我喜欢Herb Sutter关于空引用(同样无效)的文章。要点是,不要试图避免语言明确禁止的情况,尤其是在一般情况下无法可靠诊断的情况。随着时间的推移,您将获得错误的安全性,这将变得非常危险。相反,应以某种方式培训您对语言和设计接口的理解(避免原始指针,…)这减少了犯错误的机会

<>在C++中,同样地,在C中,很多情况并没有明确禁止,而是没有定义。部分原因是一些事情很难有效地诊断,部分是因为未定义的行为允许实现设计替代行为,而不是完全忽略它——这通常被现有的COMPI使用。莱勒斯


例如,在上面的例子中,任何实现都可以自由抛出异常。还有其他一些情况同样是未定义的行为,对于实现来说更难有效地诊断:在构建不同转换单元中的对象之前访问它就是这样一个例子,这就是所谓的static初始化顺序失败。

构造函数是您想要的方法(不是在初始化之前运行,而是在初始化时运行,但这应该可以)。在您的情况下,它不起作用的原因是您在这里有未定义的行为

特别是,您可以使用尚未存在的foo对象来初始化自身(例如
foo.Test()
中的
foo
还不存在)。您可以通过显式创建对象来解决此问题:

Type *t = (Type*)malloc(sizeof(*t)); 

您无法在程序中检查它,但valgrind可能会发现这种类型的错误(与任何其他未初始化的内存访问一样)。

构造函数是您想要的方法(不是在初始化之前运行,而是在初始化时运行,但这应该可以).它在你的情况下不起作用的原因是你在这里有未定义的行为

特别是,您可以使用尚未存在的foo对象来初始化自身(例如
foo.Test()
中的
foo
还不存在)。您可以通过显式创建对象来解决此问题:

Type *t = (Type*)malloc(sizeof(*t)); 

您无法在程序中检查它,但valgrind可能会发现这种类型的错误(与任何其他未初始化的内存访问一样)。

您无法阻止人们编写糟糕的代码。它的工作原理与“应该”一样:

  • 为Foo分配内存(这是“this”指针的值)
  • 通过执行:Foo::test(this)转到Foo::test,其中
  • 它通过->初始化获得值,这是随机垃圾,然后
  • 调用Foo的默认构造函数(因为返回Foo();),然后
  • 调用Foo的copy构造函数,复制右撇子Foo()
  • 就像它应该。你不能阻止人们不知道正确使用C++的方式。

    你能做的最好的事情就是有一个神奇的数字:

    Foo foo=Foo().test()
    
    这“起作用”是因为在值已经为1337的地方分配magicFlag的机会很低


    但真的,不要这样做。

    你不能阻止人们编写糟糕的代码,真的。它的工作原理就像“应该”一样:

  • 为Foo分配内存(这是“this”指针的值)
  • 通过执行:Foo::test(this)转到Foo::test,其中
  • 它通过->初始化获得值,这是随机垃圾,然后
  • 调用Foo的默认构造函数(因为返回Foo();),然后