C ++中静态声明的结构的范围是什么

时间:2019-03-01 09:45:45

标签: c++

自从我用c ++做任何事情以来已经有一段时间了,所以请帮助我解决这个问题。

我有一个结构,该结构在作用域中声明,然后放入映射中。为什么这个实例仍然不在范围之内。不应释放分配的实例吗?

#include <iostream>
#include <map>
#include <iterator>

struct foo {
  int key;
  int val;
};

int main() {
  std::map<int,foo> map;
  for (int i=0; i<10; i++) {
    foo f; // allocated 1 time only?
    f.key = 1000 + i;
    if (i%2==0) {
      f.val = i;
    }
    map.insert(std::make_pair(i, f)); // f is copied into the pair?
  }

  for (std::map<int, foo>::iterator it = map.begin(); it != map.end(); ++it) {
    std::cout << it->first;
    std::cout << " :: ";
    std::cout << it->second.key;
    std::cout << " -> ";
    std::cout << it->second.val;
    std::cout << std::endl;
  }
}

这将生成以下内容

0 :: 1000 -> 0
1 :: 1001 -> 0
2 :: 1002 -> 2
3 :: 1003 -> 2
4 :: 1004 -> 4
5 :: 1005 -> 4
6 :: 1006 -> 6
7 :: 1007 -> 6
8 :: 1008 -> 8
9 :: 1009 -> 8

代码中的注释正确吗?

现在,说我想每隔一次仅实例化val,偶数次我希望它为0(默认值)。最安全,最有效的方法是什么?

1 个答案:

答案 0 :(得分:1)

容器包含值的副本,这些副本 具有与容器相同的寿命。这是 称为“价值语义学”,是C ++的关键组成部分

#include <iostream>
#include <vector>

struct SomeType {
    int val;
};

int main()
{
    using namespace std;

    {
        int a = 3;
        int b = a;
        a = 4;
        cout << b << endl; // this prints 3, int is a value type
    }

    {
        SomeType a = {3};
        SomeType b = a;
        a.val = 4;
        cout << b.val << endl; // this prints 3, SomeType is a value type
    }

    {
        vector<int> a = {3};
        vector<int> b = a;
        a[0] = 4;
        cout << b[0] << endl; // this prints 3, vector is a value type
    }
}

如您所见,C ++(几乎)无处不在遵循价值语义。 唯一的例外是std::shared_ptr之类的东西,它们是 设计,改为使用引用/指针语义。

通常,在C ++中设计类型时,请执行int的操作。

关于您更新的问题,foo是默认构造的10次 (在for循环主体中),复制构造十次(同时创建对), 最后移动构造十次(在插入容器时)。

您的代码在一半时间内未能初始化foo::val

https://coliru.stacked-crooked.com/上编译时
我得到:

main.cpp: In function 'int main()':   main.cpp:18:35: error:
'f.foo::val' may be used uninitialized in this function [-Werror=maybe-uninitialized]
     map.insert(std::make_pair(i, f)); // f is copied into the pair?

(与std = c ++ 17 -O2 -Wall -Wextra -Werror -pedantic编译)

无法初始化变量,但仍在读取它是UB (未定义的行为),因此任何事情都可能发生;

要获得所需的输出并减少副本,请尝试:

#include <iostream>
#include <map>

struct foo {
    int key;
    int val;
};

int main() {
    std::map<int,foo> map;
    int val = 0;
    for (int i=0; i<10; i++) {
        int key = 1000 + i;
        if (i%2==0)
            val = i; // not doubled
        map.emplace(i, foo{key, val});
    }

    for (auto&& item : map) {
        std::cout << item.first << " :: " << item.second.key;
        std::cout << " -> " << item.second.val << std::endl;
    }
}