具有默认值的单参数构造函数是否与默认构造函数相同?

Is a single argument constructor with a default value the same as a default constructor?

特别是在自动调用基础 class 构造函数的上下文中:是基础 class 的单参数构造函数,具有默认值,处理方式相同(例如,如果未指定则自动调用否则)作为默认构造函数(不带参数的构造函数)?

struct base {
  base(int value = 42) {}
};
struct derived : public base {
  derived() {} // automatic call to base::base(int) ?
};

edit:以下内容与问题无关,这只是我遇到这个问题的方式。以下代码甚至没有出现我所看到的崩溃。请参阅下面的实际示例。

考虑一下:

#include <sstream>
// C++98, std::ostringstream(ios_base::openmode mode = ios_base::out) available
struct OhNo : public std::ostringstream {
  OhNo() {
  }
  void Crash() const {
    this->str();
  }
};
// later: OhNo f; f.Crash();

std::ostringstream(C++11 之前)didn't have a no-argument constructor。只有一个参数和一个默认值。 上面的 OhNo 没有调用其基础 class. 的构造函数(是的)据我所知,基础 class 构造函数被自动调用 如果 有一个 no-argument 构造函数可用。

GCC 5.4.0 可以很好地编译,但后来会出现段错误(由于 未初始化的基 class 另一个问题) . Clang 7.0.0 也可以很好地编译并运行代码也没有问题。

谁说得对?这里需要手动调用baseclass构造函数吗? 回答:没有!

受影响代码:UnitTest++ MemoryOutStream class

相关问题:https://github.com/unittest-cpp/unittest-cpp/issues/174


好的,我不知道发生了什么。下面的反汇编显示调用了基本构造函数。所以答案很可能是 "YES". 对于任何感兴趣的人,这里是重现这种非常奇怪的行为的方法:

#include "UnitTest++.h"

volatile double A() { return 2; }

TEST(Crash) {
  CHECK_CLOSE(1,A(),0.1);
}

int main()
{
 int exit_code = 0;
 exit_code = UnitTest::RunAllTests();
 return exit_code;
}

针对 libunittest++.a 使用 g++ 编译,它是 headers(例如来自 https://packages.ubuntu.com/xenial/amd64/libunittest++-dev/download)。

运行 正常:

test.cc:5: error: Failure in Crash: Unhandled exception: Crash!
FAILURE: 1 out of 1 tests failed (1 failures).
Test time: 0.00 seconds.

运行 它在 gdb 中:

(gdb) catch throw
Catchpoint 1 (throw)
(gdb) run
Starting program: /home/musteresel/huh/libunittest++-dev_1.4.0-3_amd64/data/usr/lib/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f205a0 in std::string::assign(std::string const&) () from /nix/store/hlnxw4k6931bachvg5sv0cyaissimswb-gcc-7.4.0-lib/lib/libstdc++.so.6
(gdb) bt
#0  0x00007ffff7f205a0 in std::string::assign(std::string const&) () from /nix/store/hlnxw4k6931bachvg5sv0cyaissimswb-gcc-7.4.0-lib/lib/libstdc++.so.6
#1  0x0000000000403a7a in UnitTest::MemoryOutStream::GetText() const ()
#2  0x0000000000402871 in UnitTest::CheckClose<int, double, double> (results=..., expected=@0x7fffffffbabc: 1, actual=@0x7fffffffbac0: 2, 
    tolerance=@0x7fffffffbac8: 0.10000000000000001, details=...) at ../include/unittest++/Checks.h:53
#3  0x0000000000402483 in TestCrash::RunImpl (this=0x408060 <testCrashInstance>) at test.cc:6
#4  0x0000000000402bc2 in void UnitTest::ExecuteTest<UnitTest::Test>(UnitTest::Test&, UnitTest::TestDetails const&) ()
#5  0x0000000000403255 in UnitTest::TestRunner::RunTest(UnitTest::TestResults*, UnitTest::Test*, int) const ()
#6  0x0000000000403683 in UnitTest::RunAllTests() ()
#7  0x0000000000402514 in main () at test.cc:14
(gdb) 

反汇编 - 清楚地 显示正在调用构造函数:

# in UnitTest::CheckClose<int, double, double>
  4027cb:       e8 e2 fd ff ff          callq  4025b2 <UnitTest::MemoryOutStream::MemoryOutStream()>

# in UnitTest::MemoryOutStream::MemoryOutStream()
  4025eb:       e8 60 fa ff ff          callq  402050 <std::__cxx11::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::basic_ostringstream(std::_Ios_Openmode)@plt>

来自 ISO/IEC 14882:1998(E) [class.ctor]/5

A default constructor for a class X is a constructor of class X that can be called without an argument.

默认构造函数可以有参数,只要它们都有默认参数,因此可以不带参数调用构造函数。

如果您没有在构造函数的初始化列表中为基 class 显式指定 mem-initializer,则基 class 将被初始化通过它的默认构造函数。

std::basic_ostringstream 在 C++98 中已经有一个默认构造函数(一个带有一个参数的构造函数,它有一个默认参数)。如果您仔细观察,您会发现您链接的 cppreference 页面证实了这一点……

我想在问题本身之前解决问题的动机。激励的例子是

std::ostringstream (prior to C++11) didn't have a no-argument constructor. Just one with a single argument and a default value.

尽管如此,但这不是要关注的变化。在 C++11 之前,有一个默认构造函数。它的签名是有效的(不是字面上的)

explicit basic_ostringstream();

从C++11开始,签名变成了

basic_ostringstream();

注意区别了吗?默认构造函数不再被标记 explicit。这是期望的改变。还希望将 openmode 作为其唯一参数的构造函数保持 explicit。因此,需要增加构造函数声明的数量。 (另请参阅您链接到的页面上列出的缺陷报告。)

Is a single argument constructor with a default value the same as a default constructor?

不是真的,因为前者可以用参数调用。 :P 但是对于我相信你想要的问题,是的,所有参数都具有默认值的构造函数确实用作 class.

的默认构造函数

Who's right? Is it necessary to manually call the base class constructor here?

崩溃往往意味着您有未定义的行为。至少,我不记得标准中要求将崩溃作为必需行为的任​​何部分。 :) 当行为未定义时,没有错误行为。 (大家都说得对。)