具有默认值的单个参数构造函数是否与默认构造函数相同?
Is a single argument constructor with a default value the same as a default constructor?
>特别是在自动调用基类构造函数的上下文中:具有默认值的基类的单个参数构造函数的处理方式是否与默认构造函数(没有参数的构造函数(相同(例如,如果未另行指定,则自动调用(?
struct base {
base(int value = 42) {}
};
struct derived : public base {
derived() {} // automatic call to base::base(int) ?
};
编辑:以下内容与问题无关,这只是我是如何想到这一点的。下面的代码甚至没有显示我一直看到的崩溃。有关实际示例,请参见下文。
考虑一下:
#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 之前(没有无参数构造函数。只有一个参数和一个默认值。上面的(是的,确实如此(AFAIK 如果存在无参数构造函数可用,则会自动调用基类构造函数。OhNo
不调用其基类的构造函数。
GCC 5.4.0 编译得很好,但后来出现了段错误(由于未初始化的基类另一个问题(。 Clang 7.0.0 也可以很好地编译,并且运行代码也没有问题。
谁是对的?这里是否需要手动调用基类构造函数?答:不可以!
受影响的代码:单元测试++MemoryOutStream
类
相关问题:https://github.com/unittest-cpp/unittest-cpp/issues/174
好吧,我不知道发生了什么。下面的反汇编显示调用了基构造函数。所以答案很可能是"是"。对于任何感兴趣的人,以下是重现这种非常奇怪的行为的方法:
#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;
}
使用 g++ 编译 libunittest++.a 及其标头(例如来自 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
类
X
的默认构造函数是类X
的构造函数,无需参数即可调用。
默认构造函数可以具有参数,只要它们都具有默认参数,因此可以在没有参数的情况下调用构造函数。
如果未在构造函数的初始值设定项列表中为基类显式指定mem 初始值设定项,则将通过其默认构造函数初始化基类。
std::basic_ostringstream
C++98 中已经有一个默认构造函数(一个具有一个具有默认参数的参数的构造函数(。如果你仔细观察,你会发现你链接的cpp偏好页面证实了这一点......
我想先解决问题的动机,然后再讨论问题本身。激励人的例子是
std::ostringstream
(在 C++11 之前(没有无参数构造函数。只有一个参数和一个默认值。
虽然这是真的,但这不是要关注的变化。在 C++11 之前,有一个默认构造函数。它的签名实际上是(不是字面意思(
explicit basic_ostringstream();
从 C++11 开始,签名变成了
basic_ostringstream();
注意到区别了吗?默认构造函数不再标记为explicit
。这是所期望的改变。还希望将openmode
作为其唯一参数的构造函数保持explicit
。因此,有必要增加构造函数声明的数量。(另请参阅您链接到的页面上列出的缺陷报告。
具有默认值的单个参数构造函数是否与默认构造函数相同?
不是真的,因为前者可以用参数调用。 :P但是对于这个问题,我相信你打算,是的,所有参数都有默认值的构造函数确实充当该类的默认构造函数。
谁是对的?这里是否需要手动调用基类构造函数?
崩溃往往意味着你有未定义的行为。至少,我不记得标准中要求崩溃作为所需行为的任何部分。:)当行为未定义时,没有错误的行为。(每个人都是对的。
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 初始化具有非默认构造函数的std::数组项的更好方法
- 具有默认模板类型的默认构造函数的类型推导
- 如何使用非默认构造函数实例化模板化类
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- 声明没有默认构造函数的字段
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 没有默认构造函数作为模板参数的自定义比较器
- C++17 没有默认构造函数的地图放置(私有默认构造函数)
- 使用移动调用对等构造函数unique_ptr默认构造函数
- C++复制构造函数和默认构造函数
- 将向量从 N1 缩小到 N2 项,而不触发默认构造函数并仅使用 move 语义
- 构造函数默认公共和私有变量
- 类模板构造函数默认参数
- 构造函数默认参数
- C++模板构造函数默认参数
- 在c++中设置构造函数默认值
- c++构造函数默认参数
- C++构造函数默认值头文件