Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++ c++;派生类的向量只调用构造函数一次_C++_Inheritance_Stl_Vector_Constructor - Fatal编程技术网

C++ c++;派生类的向量只调用构造函数一次

C++ c++;派生类的向量只调用构造函数一次,c++,inheritance,stl,vector,constructor,C++,Inheritance,Stl,Vector,Constructor,如果我对派生类进行大小2std::vector,则只调用一次构造函数。如果我为一个基类创建一个大小为2的向量,那么构造函数将被调用两次 我通常不会发布复制问题的完整代码,但在这种情况下,它可以非常简短: #include <iostream> #include <vector> class Base { public: Base() { std::cout << "base constructor" << std::endl; }

如果我对派生类进行大小2
std::vector
,则只调用一次构造函数。如果我为一个基类创建一个大小为2的向量,那么构造函数将被调用两次

我通常不会发布复制问题的完整代码,但在这种情况下,它可以非常简短:

#include <iostream>
#include <vector>

class Base {
public:
    Base() { std::cout << "base constructor" << std::endl; }
    virtual ~Base() {}
};

class Derived : public Base {
public:
    Derived() { std::cout << "derived constructor" << std::endl; }
};

int main() {
    std::vector<Base> base(2);
    std::cout << "----------------" << std::endl;
    std::vector<Derived> derived(2);

    return 0;
}
为什么输出不是以下内容:

base constructor
base constructor
----------------
derived constructor
derived constructor

我在Linux上使用GCC4.5.2。

你在欺骗自己:派生对象的一个默认构造调用两个构造函数

现在,您没有看到的是复制构造函数,它实际上在这两种情况下都会被调用两次

您正在调用的
vector
的构造函数对其值类型进行一个默认构造,然后将其复制到每个元素中:

//std::vector<Derived> v(2);

std::vector<Derived> v(2, Derived()); // same thing!
//std::vector v(2);
向量v(2,派生());//同样的事情!

这是对Kerrek所写内容的一点扩展:

#include <iostream>
#include <vector>

class Base {
   public:
      Base() { std::cout << "base constructor" << std::endl; }
      virtual ~Base() {
      }
      Base(const Base&){
         std::cout << "copy base constructor" << std::endl;
      }
};

class Derived : public Base {
    public:
       Derived() { std::cout << "derived constructor" << std::endl; }
       Derived(const Derived& d):Base((const Base) d){
          std::cout << "copy derived constructor" << std::endl;
       }
};

int main() {
   std::vector<Base> base(2);
   std::cout << std::endl;
   std::vector<Derived> derived(2);

   return 0;
}

这是我从VC++2010获得的输出:

base constructor
base constructor
base constructor
derived constructor
base constructor
derived constructor
Press any key to continue . . .
鉴于(GCC)4.6.1

所以看起来这是一个实现上的差异……这有点令人费解

更新 使用c++0x进行编译可以提供:

sashan@cyclops cpp  1 $  g++ -std=c++0x -o test test.cpp
sashan@cyclops cpp  $ ./test
base constructor
base constructor
base constructor
derived constructor
base constructor
derived constructor

这支持Kerrek SB的评论和回答。

我猜这只是在制作一个对象?完美的测试用例。干得好,谢谢你;永远不要为此道歉。回滚:我认为带破折号的版本更好,不是吗?对我来说,虚线出现在
基本构造函数
的第一次输出之后,并且在虚线出现之后(实际上)
基本构造函数\nDrived构造函数
。这是因为创建
Base
类型的对象需要调用
Base
构造函数,创建
Derived
类型的对象需要调用
Base
Derived
构造函数。是的,我添加了虚线,但没有运行代码。一旦我运行了代码,我就看到了@Kerek SB在回答中描述的推理错误。为什么复制构造函数用于派生类,而默认构造函数用于基类?@Lex:No,No,复制构造函数用于填充向量。将一个默认构造的对象作为原型,然后从中复制所有向量元素。只有
Derived::Derived(const-Derived&)
用于复制。@Lex:它没有!!将测试用例分为两个程序,您将看到!是
Derived()
的构造调用了一个基和一个派生构造函数。明白了。完美的因此,如果您需要一个特殊的默认构造函数,那么还应该编写一个复制构造函数和赋值运算符。具体地说,在我的实际代码中,我有一个
std::shared_ptr
,需要在构造时进行分配,我没有编写复制构造函数和赋值运算符。@Lex:C++98库设计只有一个版本的构造函数,它填充给定数量的元素,它是通过从原型复制来实现的。这就是设计。C++11添加了在适当位置构造元素的其他版本。使用
-std=c++0x
编译以查看差异。VC+2010不是c++98——它们有一些部分c++11支持,同时还有一些新的容器构造函数。。。这很可能就是这样的结果。如果使用
-std=c++0x
编译,也可以在GCC中获得放置行为。然后你也会得到直接的结构,没有副本。(事实上,我从来没有想过这一点,谢谢!只要打开C++11,你就会获得更好的效率!)你的意思是将
std::cout
放入
Base
复制构造函数而不是它的析构函数吗?
base constructor
base constructor
base constructor
derived constructor
base constructor
derived constructor
Press any key to continue . . .
g++ -o test test.cpp
sashan@cyclops cpp  $ ./test
base constructor
base constructor
derived constructor
sashan@cyclops cpp  1 $  g++ -std=c++0x -o test test.cpp
sashan@cyclops cpp  $ ./test
base constructor
base constructor
base constructor
derived constructor
base constructor
derived constructor