标签: copy-constructor

在结构体的STL Map中,为什么"[]"运算符会导致结构体的dtor被多次调用2次?

我创建了一个简单的测试用例,展示了我在一个更大的代码库中注意到的奇怪行为.这个测试用例如下.我依靠STL Map的"[]"运算符来创建指向这种结构的映射中的结构的指针.在下面的测试用例中,线...

TestStruct *thisTestStruct = &testStructMap["test"];
Run Code Online (Sandbox Code Playgroud)

...给我指针(并在地图中创建一个新条目).我注意到的奇怪之处在于,这一行不仅会导致地图中的新条目被创建(因为"[]"运算符),但由于某种原因,它会导致结构体的析构函数被多次调用两次.我显然错过了一些东西 - 非常感谢任何帮助!谢谢!

#include <iostream>
#include <string>
#include <map>

using namespace std;
struct TestStruct;

int main (int argc, char * const argv[]) {

    map<string, TestStruct> testStructMap;

    std::cout << "Marker One\n";

    //why does this line cause "~TestStruct()" to be invoked twice?
    TestStruct *thisTestStruct = &testStructMap["test"];

    std::cout << "Marker Two\n";

    return 0;
}

struct TestStruct{
    TestStruct(){
        std::cout << "TestStruct Constructor!\n";
    }

    ~TestStruct(){
        std::cout << "TestStruct Destructor!\n";
    }
};
Run Code Online (Sandbox Code Playgroud)

上面的代码输出以下内容......

/*
Marker One
TestStruct Constructor!             //makes sense …
Run Code Online (Sandbox Code Playgroud)

c++ constructor stl copy-constructor temporary-objects

8
推荐指数
3
解决办法
1634
查看次数

用自己构造对象作为参考?

我刚刚意识到这个程序编译并运行(gcc版本4.4.5/Ubuntu):

#include <iostream>
using namespace std;

class Test
{
public:
  // copyconstructor
  Test(const Test& other);
};

Test::Test(const Test& other)
{
  if (this == &other)
    cout << "copying myself" << endl;
  else
    cout << "copying something else" << endl;
}

int main(int argv, char** argc)
{
  Test a(a);              // compiles, runs and prints "copying myself"
  Test *b = new Test(*b); // compiles, runs and prints "copying something else"
}
Run Code Online (Sandbox Code Playgroud)

我想知道为什么这个甚至可以编译.我假设(就像在Java中)参数在调用方法/构造函数之前被评估,所以我怀疑这个案例必须由语言规范中的一些"特殊情况"涵盖?

问题:

  1. 有人可以解释一下(最好是参考规范)吗?
  2. 允许这个的理由是什么?
  3. 它是标准的C++还是gcc特有的?

编辑1:我刚刚意识到我甚至可以写作 int i = i;

编辑2:即使有-Wall …

c++ copy-constructor

8
推荐指数
1
解决办法
3368
查看次数

C++:默认的复制构造函数是否受到其他构造函数和析构函数的影响?

我们知道,如果声明了任何构造函数(包含复制构造函数),则不会隐式创建默认构造函数(不带参数的构造函数).使用默认复制构造函数(执行对象的浅层复制的构造函数)会发生同样的情况吗?此外,析构函数的存在是否会对此产生影响?

c++ copy-constructor default-constructor

8
推荐指数
2
解决办法
1570
查看次数

复制初始化的奇怪行为,不会调用copy-constructor!

我正在阅读直接初始化和复制初始化(§8.5/ 12)之间的区别:

T x(a);  //direct-initialization
T y = a; //copy-initialization
Run Code Online (Sandbox Code Playgroud)

我从阅读有关复制初始化的内容中了解到,它需要可访问和非显式的复制构造函数,否则程序将无法编译.我通过编写以下代码验证了它:

struct A
{
   int i;
       A(int i) : i(i) { std::cout << " A(int i)" << std::endl; }
   private:
       A(const A &a)  {  std::cout << " A(const A &)" << std::endl; }
};

int main() {
        A a = 10; //error - copy-ctor is private!
}
Run Code Online (Sandbox Code Playgroud)

GCC给出了一个错误(ideone)说:

prog.cpp:8:错误:'A :: A(const A&)'是私有的

到目前为止,一切都很好,重申Herb Sutter所说的,

复制初始化意味着在必要时首次调用用户定义的转换后,使用复制构造函数初始化对象,并且等效于"T t = u;"形式:


之后,我通过评论private …

c++ initialization copy-constructor copy-initialization

8
推荐指数
2
解决办法
717
查看次数

构造函数或复制构造函数?

通用编程和STL(中文版)一书中,它说:

X x = X() 将调用复制构造函数.

这对我来说似乎有点奇怪.我写了一个像这样的测试程序

#include <iostream>

class Test {

public:

    Test() {
        std::cout << "This is ctor\n";
    }

    Test(const Test&) {
        std::cout << "This is copy-ctor\n";
    }

};

int main(int argc, char** argv)
{

    Test t = Test();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是"This is ctor".好的,现在我很困惑,这是对的吗?

c++ constructor copy-constructor

8
推荐指数
1
解决办法
342
查看次数

什么时候模板类的特殊成员函数被实例化?

实例化模板类的特殊成员函数(特别是复制/移动构造函数和复制/移动赋值运算符)是什么时候?一旦类本身被实例化,或者仅在需要它们时?

这出现在以下情况:

template <class T, class U>
struct pair
{
    T first;                 
    U second;                

    pair() : first(), second() {}

    pair(const pair&) = default;
};

struct S
{
    S() {}
    S(const S&) = delete;
    S(S&&) = default;
};

int main()
{
    pair<int, S> p;
}
Run Code Online (Sandbox Code Playgroud)

Clang拒绝编译此代码,但有以下错误:

test.cpp:9:5: error: the parameter for this explicitly-defaulted copy constructor is const, but a member or base requires it to be
      non-const
    pair(const pair&) = default;
    ^
test.cpp:21:18: note: in instantiation of template class 'pair<int, S>' …
Run Code Online (Sandbox Code Playgroud)

c++ templates clang copy-constructor c++11

8
推荐指数
2
解决办法
4798
查看次数

为什么resize()会在超出容量时导致向量内容的复制而不是移动?

给定X下面的类(除了明确定义的特殊成员函数与此实验无关):

struct X
{
    X() { }
    X(int) { }
    X(X const&) { std::cout << "X(X const&)" << std::endl; }
    X(X&&) { std::cout << "X(X&&)" << std::endl; }
};
Run Code Online (Sandbox Code Playgroud)

以下程序创建一个类型对象的向量X并调整其大小,以便超出其容量并强制重新分配:

#include <iostream>
#include <vector>

int main()
{
    std::vector<X> v(5);
    v.resize(v.capacity() + 1);
}
Run Code Online (Sandbox Code Playgroud)

由于class X提供了一个移动构造函数,我希望在重新分配之后将向量的先前内容移动到新存储中.相当令人惊讶的是,情况似乎并非如此,我得到的输出是:

X(X const&)
X(X const&)
X(X const&)
X(X const&)
X(X const&)
Run Code Online (Sandbox Code Playgroud)

为什么?

c++ copy-constructor move-semantics c++11

8
推荐指数
2
解决办法
2124
查看次数

GCC:模板构造函数在需要copy-constructor时实例化

在下面的示例中,GCC >= 4.7实例化模板构造函数(您可以通过读取错误消息来观察),尽管只需要隐式生成的复制构造函数.

#include <type_traits>

// 'ambiguous' is ambiguous for 'ambiguous<int, int>'
template<typename A, typename B> 
struct ambiguous : std::false_type {};

template<typename T> 
struct ambiguous<int, T> : std::true_type {};

template<typename T> 
struct ambiguous<T, int> : std::true_type {};

// quantity
template<typename Type>
class quantity
{
public:
    quantity() = default;

    // Copy-constructor is implicitly created

    // Template constructor
    template<
        typename T,
        typename = typename std::enable_if<ambiguous<Type, T>::value>::type
    >
    quantity(quantity<T>) {}

    template<
        typename T,
        typename = typename std::enable_if<ambiguous<Type, T>::value>::type
    >
    void set(quantity<T>) …
Run Code Online (Sandbox Code Playgroud)

c++ gcc copy-constructor

8
推荐指数
1
解决办法
459
查看次数

复制和修改std :: strings时出现无法解释的差异

在下面的代码中,"情境1" 在所有测试的编译器上按预期工作,但"情况2"似乎根据所使用的编译器而表现不同.

作为示例,MSVC使sit1和sit2产生相同的结果,但是当使用gcc/clang和libstdc ++时,修改发生在原始字符串和它的副本(有点像COW字符串),即使我正在使用C +构建+11开关.

#include <iostream>
#include <string>

int main() {

   // situation 1
   {
      std::string x0 = "12345678";
      std::string x1 = x0;

      char* ptr = &x0[0] + 3;

      (*ptr) = ' ';

      std::cout << "1. x0: " << x0 << "\n";
      std::cout << "1. x1: " << x1 << "\n";

      if ((&x0[0]) == x0.data()) std::cout << "1. ptrs are equal\n";

   }

   // situation 2
   {
      std::string x0 = "12345678";
      std::string x1 = x0; …
Run Code Online (Sandbox Code Playgroud)

c++ string copy-constructor c++11

8
推荐指数
1
解决办法
200
查看次数

是否始终隐式定义复制构造函数,或仅在使用它们时定义?

请考虑以下代码:

#include <memory>
#include <vector>

class A
{
private:
  std::vector<std::unique_ptr<int>> _vals;
};

int main()
{
  A a;
  //A a2(a);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器A没有问题地编译它,除非我取消注释A a2(a);它抱怨复制构造函数std::unique_ptr被删除的那一行,因此我不能复制构造A.然而,即使我将该行留下注释,编译器B也会提出投诉.也就是说,当我实际尝试使用它时,编译器A只生成一个隐式定义的复制构造函数,而编译器B则无条件地这样做.哪一个是正确的?请注意,如果我使用std::unique_ptr<int> _vals;而不是std::vector<std::unique_ptr<int>> _vals;两个编译器正确地隐式删除复制构造函数和赋值运算符(std::unique_ptr具有显式删除的复制构造函数,而std::vector不是).

(注:获取代码编译器B到编译是很容易的 - 只要明确地删除拷贝构造函数和赋值运算符,并且它能够正常工作这不是问题的问题,它是要了解正确的行为.)

c++ copy-constructor assignment-operator language-lawyer c++11

8
推荐指数
1
解决办法
277
查看次数